From fa5a2d87d9574f66b3daedc38b4e3f0efae529c8 Mon Sep 17 00:00:00 2001 From: "Aaron J. Seigo" Date: Mon, 3 Nov 2008 23:03:26 +0000 Subject: [PATCH] bum-de-dum! plasma to kdelibs. svn path=/trunk/KDE/kdelibs/; revision=879757 --- CMakeLists.txt | 311 +--- Mainpage.dox | 104 +- kdm/CMakeLists.txt | 47 + kdm/Messages.sh | 4 + kdm/kgreet_classic.cpp | 484 +++++++ kdm/kgreet_classic.h | 84 ++ kdm/kgreet_generic.cpp | 354 +++++ kdm/kgreet_generic.h | 84 ++ kdm/kgreet_winbind.cpp | 627 +++++++++ kdm/kgreet_winbind.h | 94 ++ kdm/kgreeterplugin.h | 410 ++++++ ksysguard/CMakeLists.txt | 13 + ksysguard/config-ksysguard.h.cmake | 8 + ksysguard/lsofui/CMakeLists.txt | 33 + ksysguard/lsofui/LsofSearchWidget.cpp | 46 + ksysguard/lsofui/LsofSearchWidget.h | 45 + ksysguard/lsofui/LsofSearchWidget.ui | 54 + ksysguard/lsofui/Messages.sh | 2 + ksysguard/lsofui/ksysguardlsof.widgets | 8 + ksysguard/lsofui/lsof.cpp | 86 ++ ksysguard/lsofui/lsof.h | 83 ++ ksysguard/processcore/CMakeLists.txt | 28 + ksysguard/processcore/Messages.sh | 2 + ksysguard/processcore/process.cpp | 246 ++++ ksysguard/processcore/process.h | 160 +++ ksysguard/processcore/processes.cpp | 398 ++++++ ksysguard/processcore/processes.h | 224 +++ ksysguard/processcore/processes_base_p.cpp | 22 + ksysguard/processcore/processes_base_p.h | 139 ++ ksysguard/processcore/processes_freebsd_p.cpp | 307 ++++ ksysguard/processcore/processes_linux_p.cpp | 517 +++++++ ksysguard/processcore/processes_local_p.cpp | 37 + ksysguard/processcore/processes_local_p.h | 70 + ksysguard/processcore/processes_netbsd_p.cpp | 292 ++++ ksysguard/processcore/processes_openbsd_p.cpp | 306 ++++ ksysguard/processcore/processes_remote_p.cpp | 267 ++++ ksysguard/processcore/processes_remote_p.h | 78 ++ ksysguard/processcore/processes_solaris_p.cpp | 100 ++ ksysguard/processui/CMakeLists.txt | 91 ++ ksysguard/processui/DisplayProcessDlg.cpp | 100 ++ ksysguard/processui/DisplayProcessDlg.h | 53 + ksysguard/processui/DisplayProcessUi.ui | 170 +++ ksysguard/processui/KMonitorProcessIO.cpp | 330 +++++ ksysguard/processui/KMonitorProcessIO.h | 115 ++ ksysguard/processui/KMonitorProcessIO.widgets | 7 + ksysguard/processui/KTextEditVT.cpp | 170 +++ ksysguard/processui/KTextEditVT.h | 104 ++ ksysguard/processui/Messages.sh | 2 + ksysguard/processui/ProcessFilter.cc | 149 ++ ksysguard/processui/ProcessFilter.h | 56 + ksysguard/processui/ProcessModel.cc | 1245 +++++++++++++++++ ksysguard/processui/ProcessModel.h | 143 ++ ksysguard/processui/ProcessModel_p.h | 186 +++ ksysguard/processui/ProcessWidgetUI.ui | 155 ++ ksysguard/processui/ReniceDlg.cc | 180 +++ ksysguard/processui/ReniceDlg.h | 67 + ksysguard/processui/ReniceDlgUi.ui | 443 ++++++ ksysguard/processui/ksysguard.widgets | 17 + ksysguard/processui/ksysguardprocesslist.cpp | 1140 +++++++++++++++ ksysguard/processui/ksysguardprocesslist.h | 202 +++ ksysguard/tests/CMakeLists.txt | 12 + ksysguard/tests/guitest.cpp | 47 + ksysguard/tests/guitest.h | 32 + ksysguard/tests/processtest.cpp | 124 ++ ksysguard/tests/processtest.h | 41 + kworkspace/CMakeLists.txt | 28 + kworkspace/Mainpage.dox | 21 + kworkspace/Messages.sh | 2 + kworkspace/interface_util.h | 26 + kworkspace/kdisplaymanager.cpp | 458 ++++++ kworkspace/kdisplaymanager.h | 102 ++ kworkspace/kwindowlistmenu.cpp | 228 +++ kworkspace/kwindowlistmenu.h | 79 ++ kworkspace/kworkspace.cpp | 236 ++++ kworkspace/kworkspace.h | 150 ++ kworkspace/kworkspace_p.h | 49 + libplasmaclock/CMakeLists.txt | 23 + libplasmaclock/Messages.sh | 2 + libplasmaclock/calendar.cpp | 206 +++ libplasmaclock/calendar.h | 71 + libplasmaclock/calendar.ui | 42 + libplasmaclock/calendartable.cpp | 533 +++++++ libplasmaclock/calendartable.h | 90 ++ libplasmaclock/clockapplet.cpp | 379 +++++ libplasmaclock/clockapplet.h | 82 ++ libplasmaclock/clocknumber.cpp | 71 + libplasmaclock/clocknumber.h | 43 + libplasmaclock/plasmaclock_export.h | 40 + libplasmaclock/timezonesConfig.ui | 96 ++ libplasmaclock/toolbutton.cpp | 127 ++ libplasmaclock/toolbutton.h | 53 + nepomukquery/CMakeLists.txt | 41 + nepomukquery/Messages.sh | 2 + nepomukquery/dbusoperators.cpp | 341 +++++ nepomukquery/dbusoperators.h | 48 + nepomukquery/nepomukquery_export.h | 36 + nepomukquery/query.cpp | 195 +++ nepomukquery/query.h | 122 ++ nepomukquery/queryparser.cpp | 279 ++++ nepomukquery/queryparser.h | 49 + nepomukquery/qurlhash.h | 31 + nepomukquery/result.cpp | 139 ++ nepomukquery/result.h | 72 + nepomukquery/term.cpp | 363 +++++ nepomukquery/term.h | 281 ++++ nepomukqueryclient/CMakeLists.txt | 50 + .../nepomukqueryclient_export.h | 36 + nepomukqueryclient/org.kde.nepomuk.Query.xml | 16 + .../org.kde.nepomuk.QueryService.xml | 16 + nepomukqueryclient/querymetatype.h | 8 + nepomukqueryclient/queryserviceclient.cpp | 232 +++ nepomukqueryclient/queryserviceclient.h | 161 +++ plasma/CMakeLists.txt | 299 ++++ plasma/Mainpage.dox | 100 ++ Messages.sh => plasma/Messages.sh | 0 README => plasma/README | 0 .../abstractrunner.cpp | 0 abstractrunner.h => plasma/abstractrunner.h | 0 .../animationdriver.cpp | 0 animationdriver.h => plasma/animationdriver.h | 0 animator.cpp => plasma/animator.cpp | 0 animator.h => plasma/animator.h | 0 applet.cpp => plasma/applet.cpp | 0 applet.h => plasma/applet.h | 0 configloader.cpp => plasma/configloader.cpp | 0 configloader.h => plasma/configloader.h | 0 containment.cpp => plasma/containment.cpp | 0 containment.h => plasma/containment.h | 0 context.cpp => plasma/context.cpp | 0 context.h => plasma/context.h | 0 corona.cpp => plasma/corona.cpp | 0 corona.h => plasma/corona.h | 0 datacontainer.cpp => plasma/datacontainer.cpp | 0 datacontainer.h => plasma/datacontainer.h | 0 dataengine.cpp => plasma/dataengine.cpp | 0 dataengine.h => plasma/dataengine.h | 0 .../dataenginemanager.cpp | 0 .../dataenginemanager.h | 0 delegate.cpp => plasma/delegate.cpp | 0 delegate.h => plasma/delegate.h | 0 dialog.cpp => plasma/dialog.cpp | 0 dialog.h => plasma/dialog.h | 0 {effects => plasma/effects}/blur.cpp | 0 extender.cpp => plasma/extender.cpp | 0 extender.h => plasma/extender.h | 0 extenderitem.cpp => plasma/extenderitem.cpp | 0 extenderitem.h => plasma/extenderitem.h | 0 framesvg.cpp => plasma/framesvg.cpp | 0 framesvg.h => plasma/framesvg.h | 0 glapplet.cpp => plasma/glapplet.cpp | 0 glapplet.h => plasma/glapplet.h | 0 {includes => plasma/includes}/AbstractRunner | 0 {includes => plasma/includes}/AnimationDriver | 0 {includes => plasma/includes}/Animator | 0 {includes => plasma/includes}/Applet | 0 {includes => plasma/includes}/AppletScript | 0 {includes => plasma/includes}/BusyWidget | 0 {includes => plasma/includes}/CheckBox | 0 {includes => plasma/includes}/ComboBox | 0 {includes => plasma/includes}/ConfigLoader | 0 {includes => plasma/includes}/Containment | 0 {includes => plasma/includes}/Context | 0 {includes => plasma/includes}/Corona | 0 {includes => plasma/includes}/DataContainer | 0 {includes => plasma/includes}/DataEngine | 0 .../includes}/DataEngineManager | 0 .../includes}/DataEngineScript | 0 {includes => plasma/includes}/Delegate | 0 {includes => plasma/includes}/Dialog | 0 {includes => plasma/includes}/Extender | 0 {includes => plasma/includes}/ExtenderItem | 0 {includes => plasma/includes}/FlashingLabel | 0 {includes => plasma/includes}/Frame | 0 {includes => plasma/includes}/FrameSvg | 0 {includes => plasma/includes}/GLApplet | 0 {includes => plasma/includes}/GroupBox | 0 {includes => plasma/includes}/IconWidget | 0 {includes => plasma/includes}/Label | 0 {includes => plasma/includes}/LineEdit | 0 {includes => plasma/includes}/Meter | 0 {includes => plasma/includes}/Package | 0 {includes => plasma/includes}/PackageMetadata | 0 .../includes}/PackageStructure | 0 {includes => plasma/includes}/PaintUtils | 0 {includes => plasma/includes}/Plasma | 0 {includes => plasma/includes}/PopupApplet | 0 {includes => plasma/includes}/PushButton | 0 {includes => plasma/includes}/QueryMatch | 0 {includes => plasma/includes}/RadioButton | 0 {includes => plasma/includes}/RunnerContext | 0 {includes => plasma/includes}/RunnerManager | 0 {includes => plasma/includes}/RunnerScript | 0 {includes => plasma/includes}/ScriptEngine | 0 {includes => plasma/includes}/ScrollBar | 0 {includes => plasma/includes}/Service | 0 {includes => plasma/includes}/ServiceJob | 0 {includes => plasma/includes}/SignalPlotter | 0 {includes => plasma/includes}/Slider | 0 {includes => plasma/includes}/Svg | 0 {includes => plasma/includes}/SvgWidget | 0 {includes => plasma/includes}/TabBar | 0 {includes => plasma/includes}/TextEdit | 0 {includes => plasma/includes}/Theme | 0 {includes => plasma/includes}/ToolTipManager | 0 {includes => plasma/includes}/TreeView | 0 {includes => plasma/includes}/UiLoader | 0 {includes => plasma/includes}/Version | 0 {includes => plasma/includes}/View | 0 {includes => plasma/includes}/Wallpaper | 0 {includes => plasma/includes}/WebView | 0 package.cpp => plasma/package.cpp | 0 package.h => plasma/package.h | 0 .../packagemetadata.cpp | 0 packagemetadata.h => plasma/packagemetadata.h | 0 .../packagestructure.cpp | 0 .../packagestructure.h | 0 paintutils.cpp => plasma/paintutils.cpp | 0 paintutils.h => plasma/paintutils.h | 0 plasma.cpp => plasma/plasma.cpp | 0 plasma.h => plasma/plasma.h | 0 plasma_export.h => plasma/plasma_export.h | 0 popupapplet.cpp => plasma/popupapplet.cpp | 0 popupapplet.h => plasma/popupapplet.h | 0 {private => plasma/private}/applet_p.h | 0 {private => plasma/private}/applethandle.cpp | 0 {private => plasma/private}/applethandle_p.h | 0 {private => plasma/private}/containment_p.h | 0 .../private}/datacontainer_p.cpp | 0 {private => plasma/private}/datacontainer_p.h | 0 {private => plasma/private}/dataengine_p.h | 0 .../private}/desktoptoolbox.cpp | 0 .../private}/desktoptoolbox_p.h | 0 {private => plasma/private}/extender_p.h | 0 .../private}/extenderapplet.cpp | 0 .../private}/extenderapplet_p.h | 0 {private => plasma/private}/extenderitem_p.h | 0 {private => plasma/private}/nativetabbar.cpp | 0 {private => plasma/private}/nativetabbar_p.h | 0 {private => plasma/private}/packages.cpp | 0 {private => plasma/private}/packages_p.h | 0 {private => plasma/private}/paneltoolbox.cpp | 0 {private => plasma/private}/paneltoolbox_p.h | 0 {private => plasma/private}/popupapplet_p.h | 0 {private => plasma/private}/service_p.h | 0 {private => plasma/private}/sharedtimer_p.h | 0 {private => plasma/private}/style.cpp | 0 {private => plasma/private}/style.h | 0 {private => plasma/private}/toolbox.cpp | 0 {private => plasma/private}/toolbox_p.h | 0 {private => plasma/private}/tooltip.cpp | 0 {private => plasma/private}/tooltip_p.h | 0 {private => plasma/private}/windowpreview.cpp | 0 {private => plasma/private}/windowpreview_p.h | 0 querymatch.cpp => plasma/querymatch.cpp | 0 querymatch.h => plasma/querymatch.h | 0 runnercontext.cpp => plasma/runnercontext.cpp | 0 runnercontext.h => plasma/runnercontext.h | 0 runnermanager.cpp => plasma/runnermanager.cpp | 0 runnermanager.h => plasma/runnermanager.h | 0 .../scripting}/appletscript.cpp | 0 .../scripting}/appletscript.h | 0 .../scripting}/dataenginescript.cpp | 0 .../scripting}/dataenginescript.h | 0 .../scripting}/plasmoids.knsrc | 0 .../scripting}/runnerscript.cpp | 0 .../scripting}/runnerscript.h | 0 .../scripting}/scriptengine.cpp | 0 .../scripting}/scriptengine.h | 0 {scripting => plasma/scripting}/uiloader.cpp | 0 {scripting => plasma/scripting}/uiloader.h | 0 service.cpp => plasma/service.cpp | 0 service.h => plasma/service.h | 0 servicejob.cpp => plasma/servicejob.cpp | 0 servicejob.h => plasma/servicejob.h | 0 .../servicetypes}/plasma-animator.desktop | 0 .../plasma-applet-extenderapplet.desktop | 0 .../servicetypes}/plasma-applet.desktop | 0 .../servicetypes}/plasma-containment.desktop | 0 .../servicetypes}/plasma-dataengine.desktop | 0 .../plasma-packagestructure.desktop | 0 .../servicetypes}/plasma-runner.desktop | 0 .../servicetypes}/plasma-scriptengine.desktop | 0 .../servicetypes}/plasma-wallpaper.desktop | 0 svg.cpp => plasma/svg.cpp | 0 svg.h => plasma/svg.h | 0 {tests => plasma/tests}/CMakeLists.txt | 0 {tests => plasma/tests}/TODO | 0 .../tests}/packagemetadatatest.cpp | 0 .../tests}/packagemetadatatest.desktop | 0 {tests => plasma/tests}/packagemetadatatest.h | 0 .../tests}/packagestructuretest.cpp | 0 .../tests}/packagestructuretest.h | 0 {tests => plasma/tests}/plasmoidpackagerc | 0 .../tests}/plasmoidpackagetest.cpp | 0 {tests => plasma/tests}/plasmoidpackagetest.h | 0 {tests => plasma/tests}/sharedtimertest.h | 0 .../tests}/testengine/CMakeLists.txt | 0 .../plasma-dataengine-testengine.desktop | 0 .../tests}/testengine/testengine.cpp | 0 .../tests}/testengine/testengine.h | 0 theme.cpp => plasma/theme.cpp | 0 theme.h => plasma/theme.h | 0 .../tooltipcontent.cpp | 0 tooltipcontent.h => plasma/tooltipcontent.h | 0 .../tooltipmanager.cpp | 0 tooltipmanager.h => plasma/tooltipmanager.h | 0 version.cpp => plasma/version.cpp | 0 version.h => plasma/version.h | 0 view.cpp => plasma/view.cpp | 0 view.h => plasma/view.h | 0 wallpaper.cpp => plasma/wallpaper.cpp | 0 wallpaper.h => plasma/wallpaper.h | 0 {widgets => plasma/widgets}/busywidget.cpp | 0 {widgets => plasma/widgets}/busywidget.h | 0 {widgets => plasma/widgets}/checkbox.cpp | 0 {widgets => plasma/widgets}/checkbox.h | 0 {widgets => plasma/widgets}/combobox.cpp | 0 {widgets => plasma/widgets}/combobox.h | 0 {widgets => plasma/widgets}/flashinglabel.cpp | 0 {widgets => plasma/widgets}/flashinglabel.h | 0 {widgets => plasma/widgets}/frame.cpp | 0 {widgets => plasma/widgets}/frame.h | 0 {widgets => plasma/widgets}/groupbox.cpp | 0 {widgets => plasma/widgets}/groupbox.h | 0 {widgets => plasma/widgets}/iconwidget.cpp | 0 {widgets => plasma/widgets}/iconwidget.h | 0 {widgets => plasma/widgets}/iconwidget_p.h | 0 {widgets => plasma/widgets}/label.cpp | 0 {widgets => plasma/widgets}/label.h | 0 {widgets => plasma/widgets}/lineedit.cpp | 0 {widgets => plasma/widgets}/lineedit.h | 0 {widgets => plasma/widgets}/make_widget.sh | 0 {widgets => plasma/widgets}/meter.cpp | 0 {widgets => plasma/widgets}/meter.h | 0 {widgets => plasma/widgets}/pushbutton.cpp | 0 {widgets => plasma/widgets}/pushbutton.h | 0 {widgets => plasma/widgets}/radiobutton.cpp | 0 {widgets => plasma/widgets}/radiobutton.h | 0 {widgets => plasma/widgets}/scrollbar.cpp | 0 {widgets => plasma/widgets}/scrollbar.h | 0 {widgets => plasma/widgets}/signalplotter.cpp | 0 {widgets => plasma/widgets}/signalplotter.h | 0 {widgets => plasma/widgets}/slider.cpp | 0 {widgets => plasma/widgets}/slider.h | 0 {widgets => plasma/widgets}/svgwidget.cpp | 0 {widgets => plasma/widgets}/svgwidget.h | 0 {widgets => plasma/widgets}/tabbar.cpp | 0 {widgets => plasma/widgets}/tabbar.h | 0 {widgets => plasma/widgets}/template.cpp | 0 {widgets => plasma/widgets}/template.h | 0 {widgets => plasma/widgets}/textedit.cpp | 0 {widgets => plasma/widgets}/textedit.h | 0 {widgets => plasma/widgets}/treeview.cpp | 0 {widgets => plasma/widgets}/treeview.h | 0 {widgets => plasma/widgets}/webview.cpp | 0 {widgets => plasma/widgets}/webview.h | 0 private/qtjolie-branch/CMakeLists.txt | 9 - private/qtjolie-branch/Mainpage.dox | 4 - private/qtjolie-branch/sodep/CMakeLists.txt | 22 - private/qtjolie-branch/sodep/sodepfault.cpp | 108 -- private/qtjolie-branch/sodep/sodepfault.h | 52 - private/qtjolie-branch/sodep/sodephelpers_p.h | 95 -- private/qtjolie-branch/sodep/sodepmessage.cpp | 120 -- private/qtjolie-branch/sodep/sodepmessage.h | 58 - private/qtjolie-branch/sodep/sodepvalue.cpp | 206 --- private/qtjolie-branch/sodep/sodepvalue.h | 65 - private/qtjolie-branch/tests/CMakeLists.txt | 25 - .../qtjolie-branch/tests/sodepfaulttest.cpp | 100 -- .../qtjolie-branch/tests/sodepmessagetest.cpp | 98 -- .../qtjolie-branch/tests/sodepprintertest.cpp | 84 -- .../qtjolie-branch/tests/sodeptesthelpers.h | 79 -- .../qtjolie-branch/tests/sodepvaluetest.cpp | 174 --- solid/CMakeLists.txt | 2 + solid/Mainpage.dox | 8 + solid/control/CMakeLists.txt | 50 + solid/control/Messages.sh | 2 + solid/control/authentication.cpp | 336 +++++ solid/control/authentication.h | 309 ++++ solid/control/backends/CMakeLists.txt | 3 + .../backends/fakebluetooth/CMakeLists.txt | 31 + .../backends/fakebluetooth/fakebluetooth.xml | 168 +++ .../fakebluetoothinputdevice.cpp | 43 + .../fakebluetooth/fakebluetoothinputdevice.h | 93 ++ .../fakebluetooth/fakebluetoothinterface.cpp | 101 ++ .../fakebluetooth/fakebluetoothinterface.h | 231 +++ .../fakebluetooth/fakebluetoothmanager.cpp | 222 +++ .../fakebluetooth/fakebluetoothmanager.h | 66 + .../fakebluetoothremotedevice.cpp | 66 + .../fakebluetooth/fakebluetoothremotedevice.h | 175 +++ .../fakebluetooth/fakebluetoothsecurity.cpp | 31 + .../fakebluetooth/fakebluetoothsecurity.h | 34 + .../control/backends/fakebluetooth/module.cpp | 28 + .../fakebluetooth/solid_fakebluetooth.desktop | 128 ++ .../fakebluetooth/tests/CMakeLists.txt | 19 + .../fakebluetooth/tests/fakebluetoothtest.cpp | 72 + .../fakebluetooth/tests/fakebluetoothtest.h | 34 + solid/control/backends/fakenet/CMakeLists.txt | 31 + .../backends/fakenet/fakeaccesspoint.cpp | 133 ++ .../backends/fakenet/fakeaccesspoint.h | 62 + .../backends/fakenet/fakenetworking.xml | 97 ++ .../backends/fakenet/fakenetworkinterface.cpp | 114 ++ .../backends/fakenet/fakenetworkinterface.h | 65 + .../backends/fakenet/fakenetworkmanager.cpp | 285 ++++ .../backends/fakenet/fakenetworkmanager.h | 79 ++ .../fakenet/fakewirednetworkinterface.cpp | 50 + .../fakenet/fakewirednetworkinterface.h | 51 + .../fakenet/fakewirelessnetworkinterface.cpp | 77 + .../fakenet/fakewirelessnetworkinterface.h | 62 + solid/control/backends/fakenet/module.cpp | 27 + .../backends/fakenet/solid_fakenet.desktop | 126 ++ .../backends/fakenet/tests/CMakeLists.txt | 18 + .../fakenet/tests/fakenetworktest.cpp | 38 + .../backends/fakenet/tests/fakenetworktest.h | 32 + solid/control/bluetoothinputdevice.cpp | 99 ++ solid/control/bluetoothinputdevice.h | 123 ++ solid/control/bluetoothinterface.cpp | 474 +++++++ solid/control/bluetoothinterface.h | 558 ++++++++ solid/control/bluetoothmanager.cpp | 391 ++++++ solid/control/bluetoothmanager.h | 204 +++ solid/control/bluetoothremotedevice.cpp | 315 +++++ solid/control/bluetoothremotedevice.h | 165 +++ solid/control/bluetoothsecurity.cpp | 139 ++ solid/control/bluetoothsecurity.h | 184 +++ solid/control/frontendobject.cpp | 65 + solid/control/frontendobject_p.h | 49 + solid/control/ifaces/CMakeLists.txt | 40 + solid/control/ifaces/authentication.cpp | 27 + solid/control/ifaces/authentication.h | 58 + solid/control/ifaces/bluetoothinputdevice.cpp | 30 + solid/control/ifaces/bluetoothinputdevice.h | 100 ++ solid/control/ifaces/bluetoothinterface.cpp | 31 + solid/control/ifaces/bluetoothinterface.h | 517 +++++++ solid/control/ifaces/bluetoothmanager.cpp | 31 + solid/control/ifaces/bluetoothmanager.h | 172 +++ .../control/ifaces/bluetoothremotedevice.cpp | 30 + solid/control/ifaces/bluetoothremotedevice.h | 131 ++ solid/control/ifaces/bluetoothsecurity.cpp | 38 + solid/control/ifaces/bluetoothsecurity.h | 73 + solid/control/ifaces/networkcdmainterface.cpp | 27 + solid/control/ifaces/networkcdmainterface.h | 62 + solid/control/ifaces/networkgsminterface.cpp | 27 + solid/control/ifaces/networkgsminterface.h | 58 + solid/control/ifaces/networkinterface.cpp | 26 + solid/control/ifaces/networkinterface.h | 123 ++ solid/control/ifaces/networkmanager.cpp | 32 + solid/control/ifaces/networkmanager.h | 170 +++ .../control/ifaces/networkserialinterface.cpp | 27 + solid/control/ifaces/networkserialinterface.h | 58 + solid/control/ifaces/powermanager.cpp | 34 + solid/control/ifaces/powermanager.h | 245 ++++ .../control/ifaces/wirednetworkinterface.cpp | 26 + solid/control/ifaces/wirednetworkinterface.h | 85 ++ solid/control/ifaces/wirelessaccesspoint.cpp | 31 + solid/control/ifaces/wirelessaccesspoint.h | 157 +++ .../ifaces/wirelessnetworkinterface.cpp | 28 + .../control/ifaces/wirelessnetworkinterface.h | 123 ++ solid/control/managerbase.cpp | 115 ++ solid/control/managerbase_p.h | 51 + solid/control/network_p.h | 41 + solid/control/networkcdmainterface.cpp | 77 + solid/control/networkcdmainterface.h | 89 ++ solid/control/networkcdmainterface_p.h | 41 + solid/control/networkgsminterface.cpp | 78 ++ solid/control/networkgsminterface.h | 89 ++ solid/control/networkgsminterface_p.h | 41 + solid/control/networking.cpp | 323 +++++ solid/control/networking.h | 99 ++ solid/control/networking_p.h | 109 ++ solid/control/networkinterface.cpp | 122 ++ solid/control/networkinterface.h | 203 +++ solid/control/networkinterface_p.h | 42 + solid/control/networkipv4config.cpp | 232 +++ solid/control/networkipv4config.h | 96 ++ solid/control/networkmanager.cpp | 276 ++++ solid/control/networkmanager.h | 175 +++ solid/control/networkmanager_p.h | 66 + solid/control/networkserialinterface.cpp | 80 ++ solid/control/networkserialinterface.h | 90 ++ solid/control/networkserialinterface_p.h | 41 + solid/control/org.kde.Solid.Networking.xml | 17 + solid/control/powermanager.cpp | 197 +++ solid/control/powermanager.h | 314 +++++ solid/control/powermanager_p.h | 41 + solid/control/singletondefs.h | 56 + solid/control/solid_control_export.h | 56 + solid/control/solidbluetoothmanager.desktop | 68 + solid/control/soliddefs_p.h | 49 + solid/control/solidnetworkmanager.desktop | 66 + solid/control/solidpowermanager.desktop | 67 + solid/control/tests/CMakeLists.txt | 30 + solid/control/tests/solidbluetoothtest.cpp | 80 ++ solid/control/tests/solidbluetoothtest.h | 42 + solid/control/tests/solidnettest.cpp | 157 +++ solid/control/tests/solidnettest.h | 41 + solid/control/wirednetworkinterface.cpp | 96 ++ solid/control/wirednetworkinterface.h | 122 ++ solid/control/wirednetworkinterface_p.h | 41 + solid/control/wirelessaccesspoint.cpp | 165 +++ solid/control/wirelessaccesspoint.h | 186 +++ solid/control/wirelessnetworkinterface.cpp | 238 ++++ solid/control/wirelessnetworkinterface.h | 174 +++ solid/control/wirelessnetworkinterface_p.h | 58 + taskmanager/CMakeLists.txt | 55 + taskmanager/Mainpage.dox | 21 + taskmanager/Messages.sh | 2 + taskmanager/abstractgroupableitem.cpp | 118 ++ taskmanager/abstractgroupableitem.h | 127 ++ taskmanager/abstractgroupingstrategy.cpp | 240 ++++ taskmanager/abstractgroupingstrategy.h | 115 ++ taskmanager/abstractsortingstrategy.cpp | 176 +++ taskmanager/abstractsortingstrategy.h | 88 ++ taskmanager/groupmanager.cpp | 627 +++++++++ taskmanager/groupmanager.h | 153 ++ taskmanager/startup.cpp | 101 ++ taskmanager/startup.h | 95 ++ .../strategies/alphasortingstrategy.cpp | 95 ++ taskmanager/strategies/alphasortingstrategy.h | 50 + .../strategies/manualgroupingstrategy.cpp | 534 +++++++ .../strategies/manualgroupingstrategy.h | 213 +++ .../strategies/manualsortingstrategy.cpp | 157 +++ .../strategies/manualsortingstrategy.h | 65 + .../strategies/programgroupingstrategy.cpp | 190 +++ .../strategies/programgroupingstrategy.h | 77 + taskmanager/task.cpp | 1067 ++++++++++++++ taskmanager/task.h | 440 ++++++ taskmanager/taskactions.cpp | 422 ++++++ taskmanager/taskactions.h | 133 ++ taskmanager/taskactions_p.h | 165 +++ taskmanager/taskgroup.cpp | 493 +++++++ taskmanager/taskgroup.h | 136 ++ taskmanager/taskitem.cpp | 328 +++++ taskmanager/taskitem.h | 103 ++ taskmanager/taskmanager.cpp | 535 +++++++ taskmanager/taskmanager.h | 206 +++ taskmanager/taskmanager_export.h | 45 + taskmanager/taskmanager_p.h | 51 + taskmanager/taskrmbmenu.cpp | 363 +++++ taskmanager/taskrmbmenu.h | 74 + 538 files changed, 39096 insertions(+), 1691 deletions(-) create mode 100644 kdm/CMakeLists.txt create mode 100644 kdm/Messages.sh create mode 100644 kdm/kgreet_classic.cpp create mode 100644 kdm/kgreet_classic.h create mode 100644 kdm/kgreet_generic.cpp create mode 100644 kdm/kgreet_generic.h create mode 100644 kdm/kgreet_winbind.cpp create mode 100644 kdm/kgreet_winbind.h create mode 100644 kdm/kgreeterplugin.h create mode 100644 ksysguard/CMakeLists.txt create mode 100644 ksysguard/config-ksysguard.h.cmake create mode 100644 ksysguard/lsofui/CMakeLists.txt create mode 100644 ksysguard/lsofui/LsofSearchWidget.cpp create mode 100644 ksysguard/lsofui/LsofSearchWidget.h create mode 100644 ksysguard/lsofui/LsofSearchWidget.ui create mode 100755 ksysguard/lsofui/Messages.sh create mode 100644 ksysguard/lsofui/ksysguardlsof.widgets create mode 100644 ksysguard/lsofui/lsof.cpp create mode 100644 ksysguard/lsofui/lsof.h create mode 100644 ksysguard/processcore/CMakeLists.txt create mode 100755 ksysguard/processcore/Messages.sh create mode 100644 ksysguard/processcore/process.cpp create mode 100644 ksysguard/processcore/process.h create mode 100644 ksysguard/processcore/processes.cpp create mode 100644 ksysguard/processcore/processes.h create mode 100644 ksysguard/processcore/processes_base_p.cpp create mode 100644 ksysguard/processcore/processes_base_p.h create mode 100644 ksysguard/processcore/processes_freebsd_p.cpp create mode 100644 ksysguard/processcore/processes_linux_p.cpp create mode 100644 ksysguard/processcore/processes_local_p.cpp create mode 100644 ksysguard/processcore/processes_local_p.h create mode 100644 ksysguard/processcore/processes_netbsd_p.cpp create mode 100644 ksysguard/processcore/processes_openbsd_p.cpp create mode 100644 ksysguard/processcore/processes_remote_p.cpp create mode 100644 ksysguard/processcore/processes_remote_p.h create mode 100644 ksysguard/processcore/processes_solaris_p.cpp create mode 100644 ksysguard/processui/CMakeLists.txt create mode 100644 ksysguard/processui/DisplayProcessDlg.cpp create mode 100644 ksysguard/processui/DisplayProcessDlg.h create mode 100644 ksysguard/processui/DisplayProcessUi.ui create mode 100644 ksysguard/processui/KMonitorProcessIO.cpp create mode 100644 ksysguard/processui/KMonitorProcessIO.h create mode 100644 ksysguard/processui/KMonitorProcessIO.widgets create mode 100644 ksysguard/processui/KTextEditVT.cpp create mode 100644 ksysguard/processui/KTextEditVT.h create mode 100755 ksysguard/processui/Messages.sh create mode 100644 ksysguard/processui/ProcessFilter.cc create mode 100644 ksysguard/processui/ProcessFilter.h create mode 100644 ksysguard/processui/ProcessModel.cc create mode 100644 ksysguard/processui/ProcessModel.h create mode 100644 ksysguard/processui/ProcessModel_p.h create mode 100644 ksysguard/processui/ProcessWidgetUI.ui create mode 100644 ksysguard/processui/ReniceDlg.cc create mode 100644 ksysguard/processui/ReniceDlg.h create mode 100644 ksysguard/processui/ReniceDlgUi.ui create mode 100644 ksysguard/processui/ksysguard.widgets create mode 100644 ksysguard/processui/ksysguardprocesslist.cpp create mode 100644 ksysguard/processui/ksysguardprocesslist.h create mode 100644 ksysguard/tests/CMakeLists.txt create mode 100644 ksysguard/tests/guitest.cpp create mode 100644 ksysguard/tests/guitest.h create mode 100644 ksysguard/tests/processtest.cpp create mode 100644 ksysguard/tests/processtest.h create mode 100644 kworkspace/CMakeLists.txt create mode 100644 kworkspace/Mainpage.dox create mode 100644 kworkspace/Messages.sh create mode 100644 kworkspace/interface_util.h create mode 100644 kworkspace/kdisplaymanager.cpp create mode 100644 kworkspace/kdisplaymanager.h create mode 100644 kworkspace/kwindowlistmenu.cpp create mode 100644 kworkspace/kwindowlistmenu.h create mode 100644 kworkspace/kworkspace.cpp create mode 100644 kworkspace/kworkspace.h create mode 100644 kworkspace/kworkspace_p.h create mode 100644 libplasmaclock/CMakeLists.txt create mode 100755 libplasmaclock/Messages.sh create mode 100644 libplasmaclock/calendar.cpp create mode 100644 libplasmaclock/calendar.h create mode 100644 libplasmaclock/calendar.ui create mode 100644 libplasmaclock/calendartable.cpp create mode 100644 libplasmaclock/calendartable.h create mode 100644 libplasmaclock/clockapplet.cpp create mode 100644 libplasmaclock/clockapplet.h create mode 100644 libplasmaclock/clocknumber.cpp create mode 100644 libplasmaclock/clocknumber.h create mode 100644 libplasmaclock/plasmaclock_export.h create mode 100644 libplasmaclock/timezonesConfig.ui create mode 100644 libplasmaclock/toolbutton.cpp create mode 100644 libplasmaclock/toolbutton.h create mode 100644 nepomukquery/CMakeLists.txt create mode 100755 nepomukquery/Messages.sh create mode 100644 nepomukquery/dbusoperators.cpp create mode 100644 nepomukquery/dbusoperators.h create mode 100644 nepomukquery/nepomukquery_export.h create mode 100644 nepomukquery/query.cpp create mode 100644 nepomukquery/query.h create mode 100644 nepomukquery/queryparser.cpp create mode 100644 nepomukquery/queryparser.h create mode 100644 nepomukquery/qurlhash.h create mode 100644 nepomukquery/result.cpp create mode 100644 nepomukquery/result.h create mode 100644 nepomukquery/term.cpp create mode 100644 nepomukquery/term.h create mode 100644 nepomukqueryclient/CMakeLists.txt create mode 100644 nepomukqueryclient/nepomukqueryclient_export.h create mode 100644 nepomukqueryclient/org.kde.nepomuk.Query.xml create mode 100644 nepomukqueryclient/org.kde.nepomuk.QueryService.xml create mode 100644 nepomukqueryclient/querymetatype.h create mode 100644 nepomukqueryclient/queryserviceclient.cpp create mode 100644 nepomukqueryclient/queryserviceclient.h create mode 100644 plasma/CMakeLists.txt create mode 100644 plasma/Mainpage.dox rename Messages.sh => plasma/Messages.sh (100%) rename README => plasma/README (100%) rename abstractrunner.cpp => plasma/abstractrunner.cpp (100%) rename abstractrunner.h => plasma/abstractrunner.h (100%) rename animationdriver.cpp => plasma/animationdriver.cpp (100%) rename animationdriver.h => plasma/animationdriver.h (100%) rename animator.cpp => plasma/animator.cpp (100%) rename animator.h => plasma/animator.h (100%) rename applet.cpp => plasma/applet.cpp (100%) rename applet.h => plasma/applet.h (100%) rename configloader.cpp => plasma/configloader.cpp (100%) rename configloader.h => plasma/configloader.h (100%) rename containment.cpp => plasma/containment.cpp (100%) rename containment.h => plasma/containment.h (100%) rename context.cpp => plasma/context.cpp (100%) rename context.h => plasma/context.h (100%) rename corona.cpp => plasma/corona.cpp (100%) rename corona.h => plasma/corona.h (100%) rename datacontainer.cpp => plasma/datacontainer.cpp (100%) rename datacontainer.h => plasma/datacontainer.h (100%) rename dataengine.cpp => plasma/dataengine.cpp (100%) rename dataengine.h => plasma/dataengine.h (100%) rename dataenginemanager.cpp => plasma/dataenginemanager.cpp (100%) rename dataenginemanager.h => plasma/dataenginemanager.h (100%) rename delegate.cpp => plasma/delegate.cpp (100%) rename delegate.h => plasma/delegate.h (100%) rename dialog.cpp => plasma/dialog.cpp (100%) rename dialog.h => plasma/dialog.h (100%) rename {effects => plasma/effects}/blur.cpp (100%) rename extender.cpp => plasma/extender.cpp (100%) rename extender.h => plasma/extender.h (100%) rename extenderitem.cpp => plasma/extenderitem.cpp (100%) rename extenderitem.h => plasma/extenderitem.h (100%) rename framesvg.cpp => plasma/framesvg.cpp (100%) rename framesvg.h => plasma/framesvg.h (100%) rename glapplet.cpp => plasma/glapplet.cpp (100%) rename glapplet.h => plasma/glapplet.h (100%) rename {includes => plasma/includes}/AbstractRunner (100%) rename {includes => plasma/includes}/AnimationDriver (100%) rename {includes => plasma/includes}/Animator (100%) rename {includes => plasma/includes}/Applet (100%) rename {includes => plasma/includes}/AppletScript (100%) rename {includes => plasma/includes}/BusyWidget (100%) rename {includes => plasma/includes}/CheckBox (100%) rename {includes => plasma/includes}/ComboBox (100%) rename {includes => plasma/includes}/ConfigLoader (100%) rename {includes => plasma/includes}/Containment (100%) rename {includes => plasma/includes}/Context (100%) rename {includes => plasma/includes}/Corona (100%) rename {includes => plasma/includes}/DataContainer (100%) rename {includes => plasma/includes}/DataEngine (100%) rename {includes => plasma/includes}/DataEngineManager (100%) rename {includes => plasma/includes}/DataEngineScript (100%) rename {includes => plasma/includes}/Delegate (100%) rename {includes => plasma/includes}/Dialog (100%) rename {includes => plasma/includes}/Extender (100%) rename {includes => plasma/includes}/ExtenderItem (100%) rename {includes => plasma/includes}/FlashingLabel (100%) rename {includes => plasma/includes}/Frame (100%) rename {includes => plasma/includes}/FrameSvg (100%) rename {includes => plasma/includes}/GLApplet (100%) rename {includes => plasma/includes}/GroupBox (100%) rename {includes => plasma/includes}/IconWidget (100%) rename {includes => plasma/includes}/Label (100%) rename {includes => plasma/includes}/LineEdit (100%) rename {includes => plasma/includes}/Meter (100%) rename {includes => plasma/includes}/Package (100%) rename {includes => plasma/includes}/PackageMetadata (100%) rename {includes => plasma/includes}/PackageStructure (100%) rename {includes => plasma/includes}/PaintUtils (100%) rename {includes => plasma/includes}/Plasma (100%) rename {includes => plasma/includes}/PopupApplet (100%) rename {includes => plasma/includes}/PushButton (100%) rename {includes => plasma/includes}/QueryMatch (100%) rename {includes => plasma/includes}/RadioButton (100%) rename {includes => plasma/includes}/RunnerContext (100%) rename {includes => plasma/includes}/RunnerManager (100%) rename {includes => plasma/includes}/RunnerScript (100%) rename {includes => plasma/includes}/ScriptEngine (100%) rename {includes => plasma/includes}/ScrollBar (100%) rename {includes => plasma/includes}/Service (100%) rename {includes => plasma/includes}/ServiceJob (100%) rename {includes => plasma/includes}/SignalPlotter (100%) rename {includes => plasma/includes}/Slider (100%) rename {includes => plasma/includes}/Svg (100%) rename {includes => plasma/includes}/SvgWidget (100%) rename {includes => plasma/includes}/TabBar (100%) rename {includes => plasma/includes}/TextEdit (100%) rename {includes => plasma/includes}/Theme (100%) rename {includes => plasma/includes}/ToolTipManager (100%) rename {includes => plasma/includes}/TreeView (100%) rename {includes => plasma/includes}/UiLoader (100%) rename {includes => plasma/includes}/Version (100%) rename {includes => plasma/includes}/View (100%) rename {includes => plasma/includes}/Wallpaper (100%) rename {includes => plasma/includes}/WebView (100%) rename package.cpp => plasma/package.cpp (100%) rename package.h => plasma/package.h (100%) rename packagemetadata.cpp => plasma/packagemetadata.cpp (100%) rename packagemetadata.h => plasma/packagemetadata.h (100%) rename packagestructure.cpp => plasma/packagestructure.cpp (100%) rename packagestructure.h => plasma/packagestructure.h (100%) rename paintutils.cpp => plasma/paintutils.cpp (100%) rename paintutils.h => plasma/paintutils.h (100%) rename plasma.cpp => plasma/plasma.cpp (100%) rename plasma.h => plasma/plasma.h (100%) rename plasma_export.h => plasma/plasma_export.h (100%) rename popupapplet.cpp => plasma/popupapplet.cpp (100%) rename popupapplet.h => plasma/popupapplet.h (100%) rename {private => plasma/private}/applet_p.h (100%) rename {private => plasma/private}/applethandle.cpp (100%) rename {private => plasma/private}/applethandle_p.h (100%) rename {private => plasma/private}/containment_p.h (100%) rename {private => plasma/private}/datacontainer_p.cpp (100%) rename {private => plasma/private}/datacontainer_p.h (100%) rename {private => plasma/private}/dataengine_p.h (100%) rename {private => plasma/private}/desktoptoolbox.cpp (100%) rename {private => plasma/private}/desktoptoolbox_p.h (100%) rename {private => plasma/private}/extender_p.h (100%) rename {private => plasma/private}/extenderapplet.cpp (100%) rename {private => plasma/private}/extenderapplet_p.h (100%) rename {private => plasma/private}/extenderitem_p.h (100%) rename {private => plasma/private}/nativetabbar.cpp (100%) rename {private => plasma/private}/nativetabbar_p.h (100%) rename {private => plasma/private}/packages.cpp (100%) rename {private => plasma/private}/packages_p.h (100%) rename {private => plasma/private}/paneltoolbox.cpp (100%) rename {private => plasma/private}/paneltoolbox_p.h (100%) rename {private => plasma/private}/popupapplet_p.h (100%) rename {private => plasma/private}/service_p.h (100%) rename {private => plasma/private}/sharedtimer_p.h (100%) rename {private => plasma/private}/style.cpp (100%) rename {private => plasma/private}/style.h (100%) rename {private => plasma/private}/toolbox.cpp (100%) rename {private => plasma/private}/toolbox_p.h (100%) rename {private => plasma/private}/tooltip.cpp (100%) rename {private => plasma/private}/tooltip_p.h (100%) rename {private => plasma/private}/windowpreview.cpp (100%) rename {private => plasma/private}/windowpreview_p.h (100%) rename querymatch.cpp => plasma/querymatch.cpp (100%) rename querymatch.h => plasma/querymatch.h (100%) rename runnercontext.cpp => plasma/runnercontext.cpp (100%) rename runnercontext.h => plasma/runnercontext.h (100%) rename runnermanager.cpp => plasma/runnermanager.cpp (100%) rename runnermanager.h => plasma/runnermanager.h (100%) rename {scripting => plasma/scripting}/appletscript.cpp (100%) rename {scripting => plasma/scripting}/appletscript.h (100%) rename {scripting => plasma/scripting}/dataenginescript.cpp (100%) rename {scripting => plasma/scripting}/dataenginescript.h (100%) rename {scripting => plasma/scripting}/plasmoids.knsrc (100%) rename {scripting => plasma/scripting}/runnerscript.cpp (100%) rename {scripting => plasma/scripting}/runnerscript.h (100%) rename {scripting => plasma/scripting}/scriptengine.cpp (100%) rename {scripting => plasma/scripting}/scriptengine.h (100%) rename {scripting => plasma/scripting}/uiloader.cpp (100%) rename {scripting => plasma/scripting}/uiloader.h (100%) rename service.cpp => plasma/service.cpp (100%) rename service.h => plasma/service.h (100%) rename servicejob.cpp => plasma/servicejob.cpp (100%) rename servicejob.h => plasma/servicejob.h (100%) rename {servicetypes => plasma/servicetypes}/plasma-animator.desktop (100%) rename {servicetypes => plasma/servicetypes}/plasma-applet-extenderapplet.desktop (100%) rename {servicetypes => plasma/servicetypes}/plasma-applet.desktop (100%) rename {servicetypes => plasma/servicetypes}/plasma-containment.desktop (100%) rename {servicetypes => plasma/servicetypes}/plasma-dataengine.desktop (100%) rename {servicetypes => plasma/servicetypes}/plasma-packagestructure.desktop (100%) rename {servicetypes => plasma/servicetypes}/plasma-runner.desktop (100%) rename {servicetypes => plasma/servicetypes}/plasma-scriptengine.desktop (100%) rename {servicetypes => plasma/servicetypes}/plasma-wallpaper.desktop (100%) rename svg.cpp => plasma/svg.cpp (100%) rename svg.h => plasma/svg.h (100%) rename {tests => plasma/tests}/CMakeLists.txt (100%) rename {tests => plasma/tests}/TODO (100%) rename {tests => plasma/tests}/packagemetadatatest.cpp (100%) rename {tests => plasma/tests}/packagemetadatatest.desktop (100%) rename {tests => plasma/tests}/packagemetadatatest.h (100%) rename {tests => plasma/tests}/packagestructuretest.cpp (100%) rename {tests => plasma/tests}/packagestructuretest.h (100%) rename {tests => plasma/tests}/plasmoidpackagerc (100%) rename {tests => plasma/tests}/plasmoidpackagetest.cpp (100%) rename {tests => plasma/tests}/plasmoidpackagetest.h (100%) rename {tests => plasma/tests}/sharedtimertest.h (100%) rename {tests => plasma/tests}/testengine/CMakeLists.txt (100%) rename {tests => plasma/tests}/testengine/plasma-dataengine-testengine.desktop (100%) rename {tests => plasma/tests}/testengine/testengine.cpp (100%) rename {tests => plasma/tests}/testengine/testengine.h (100%) rename theme.cpp => plasma/theme.cpp (100%) rename theme.h => plasma/theme.h (100%) rename tooltipcontent.cpp => plasma/tooltipcontent.cpp (100%) rename tooltipcontent.h => plasma/tooltipcontent.h (100%) rename tooltipmanager.cpp => plasma/tooltipmanager.cpp (100%) rename tooltipmanager.h => plasma/tooltipmanager.h (100%) rename version.cpp => plasma/version.cpp (100%) rename version.h => plasma/version.h (100%) rename view.cpp => plasma/view.cpp (100%) rename view.h => plasma/view.h (100%) rename wallpaper.cpp => plasma/wallpaper.cpp (100%) rename wallpaper.h => plasma/wallpaper.h (100%) rename {widgets => plasma/widgets}/busywidget.cpp (100%) rename {widgets => plasma/widgets}/busywidget.h (100%) rename {widgets => plasma/widgets}/checkbox.cpp (100%) rename {widgets => plasma/widgets}/checkbox.h (100%) rename {widgets => plasma/widgets}/combobox.cpp (100%) rename {widgets => plasma/widgets}/combobox.h (100%) rename {widgets => plasma/widgets}/flashinglabel.cpp (100%) rename {widgets => plasma/widgets}/flashinglabel.h (100%) rename {widgets => plasma/widgets}/frame.cpp (100%) rename {widgets => plasma/widgets}/frame.h (100%) rename {widgets => plasma/widgets}/groupbox.cpp (100%) rename {widgets => plasma/widgets}/groupbox.h (100%) rename {widgets => plasma/widgets}/iconwidget.cpp (100%) rename {widgets => plasma/widgets}/iconwidget.h (100%) rename {widgets => plasma/widgets}/iconwidget_p.h (100%) rename {widgets => plasma/widgets}/label.cpp (100%) rename {widgets => plasma/widgets}/label.h (100%) rename {widgets => plasma/widgets}/lineedit.cpp (100%) rename {widgets => plasma/widgets}/lineedit.h (100%) rename {widgets => plasma/widgets}/make_widget.sh (100%) rename {widgets => plasma/widgets}/meter.cpp (100%) rename {widgets => plasma/widgets}/meter.h (100%) rename {widgets => plasma/widgets}/pushbutton.cpp (100%) rename {widgets => plasma/widgets}/pushbutton.h (100%) rename {widgets => plasma/widgets}/radiobutton.cpp (100%) rename {widgets => plasma/widgets}/radiobutton.h (100%) rename {widgets => plasma/widgets}/scrollbar.cpp (100%) rename {widgets => plasma/widgets}/scrollbar.h (100%) rename {widgets => plasma/widgets}/signalplotter.cpp (100%) rename {widgets => plasma/widgets}/signalplotter.h (100%) rename {widgets => plasma/widgets}/slider.cpp (100%) rename {widgets => plasma/widgets}/slider.h (100%) rename {widgets => plasma/widgets}/svgwidget.cpp (100%) rename {widgets => plasma/widgets}/svgwidget.h (100%) rename {widgets => plasma/widgets}/tabbar.cpp (100%) rename {widgets => plasma/widgets}/tabbar.h (100%) rename {widgets => plasma/widgets}/template.cpp (100%) rename {widgets => plasma/widgets}/template.h (100%) rename {widgets => plasma/widgets}/textedit.cpp (100%) rename {widgets => plasma/widgets}/textedit.h (100%) rename {widgets => plasma/widgets}/treeview.cpp (100%) rename {widgets => plasma/widgets}/treeview.h (100%) rename {widgets => plasma/widgets}/webview.cpp (100%) rename {widgets => plasma/widgets}/webview.h (100%) delete mode 100644 private/qtjolie-branch/CMakeLists.txt delete mode 100644 private/qtjolie-branch/Mainpage.dox delete mode 100644 private/qtjolie-branch/sodep/CMakeLists.txt delete mode 100644 private/qtjolie-branch/sodep/sodepfault.cpp delete mode 100644 private/qtjolie-branch/sodep/sodepfault.h delete mode 100644 private/qtjolie-branch/sodep/sodephelpers_p.h delete mode 100644 private/qtjolie-branch/sodep/sodepmessage.cpp delete mode 100644 private/qtjolie-branch/sodep/sodepmessage.h delete mode 100644 private/qtjolie-branch/sodep/sodepvalue.cpp delete mode 100644 private/qtjolie-branch/sodep/sodepvalue.h delete mode 100644 private/qtjolie-branch/tests/CMakeLists.txt delete mode 100644 private/qtjolie-branch/tests/sodepfaulttest.cpp delete mode 100644 private/qtjolie-branch/tests/sodepmessagetest.cpp delete mode 100644 private/qtjolie-branch/tests/sodepprintertest.cpp delete mode 100644 private/qtjolie-branch/tests/sodeptesthelpers.h delete mode 100644 private/qtjolie-branch/tests/sodepvaluetest.cpp create mode 100644 solid/CMakeLists.txt create mode 100644 solid/Mainpage.dox create mode 100644 solid/control/CMakeLists.txt create mode 100755 solid/control/Messages.sh create mode 100644 solid/control/authentication.cpp create mode 100644 solid/control/authentication.h create mode 100644 solid/control/backends/CMakeLists.txt create mode 100644 solid/control/backends/fakebluetooth/CMakeLists.txt create mode 100644 solid/control/backends/fakebluetooth/fakebluetooth.xml create mode 100644 solid/control/backends/fakebluetooth/fakebluetoothinputdevice.cpp create mode 100644 solid/control/backends/fakebluetooth/fakebluetoothinputdevice.h create mode 100644 solid/control/backends/fakebluetooth/fakebluetoothinterface.cpp create mode 100644 solid/control/backends/fakebluetooth/fakebluetoothinterface.h create mode 100644 solid/control/backends/fakebluetooth/fakebluetoothmanager.cpp create mode 100644 solid/control/backends/fakebluetooth/fakebluetoothmanager.h create mode 100644 solid/control/backends/fakebluetooth/fakebluetoothremotedevice.cpp create mode 100644 solid/control/backends/fakebluetooth/fakebluetoothremotedevice.h create mode 100644 solid/control/backends/fakebluetooth/fakebluetoothsecurity.cpp create mode 100644 solid/control/backends/fakebluetooth/fakebluetoothsecurity.h create mode 100644 solid/control/backends/fakebluetooth/module.cpp create mode 100644 solid/control/backends/fakebluetooth/solid_fakebluetooth.desktop create mode 100644 solid/control/backends/fakebluetooth/tests/CMakeLists.txt create mode 100644 solid/control/backends/fakebluetooth/tests/fakebluetoothtest.cpp create mode 100644 solid/control/backends/fakebluetooth/tests/fakebluetoothtest.h create mode 100644 solid/control/backends/fakenet/CMakeLists.txt create mode 100644 solid/control/backends/fakenet/fakeaccesspoint.cpp create mode 100644 solid/control/backends/fakenet/fakeaccesspoint.h create mode 100644 solid/control/backends/fakenet/fakenetworking.xml create mode 100644 solid/control/backends/fakenet/fakenetworkinterface.cpp create mode 100644 solid/control/backends/fakenet/fakenetworkinterface.h create mode 100644 solid/control/backends/fakenet/fakenetworkmanager.cpp create mode 100644 solid/control/backends/fakenet/fakenetworkmanager.h create mode 100644 solid/control/backends/fakenet/fakewirednetworkinterface.cpp create mode 100644 solid/control/backends/fakenet/fakewirednetworkinterface.h create mode 100644 solid/control/backends/fakenet/fakewirelessnetworkinterface.cpp create mode 100644 solid/control/backends/fakenet/fakewirelessnetworkinterface.h create mode 100644 solid/control/backends/fakenet/module.cpp create mode 100644 solid/control/backends/fakenet/solid_fakenet.desktop create mode 100644 solid/control/backends/fakenet/tests/CMakeLists.txt create mode 100644 solid/control/backends/fakenet/tests/fakenetworktest.cpp create mode 100644 solid/control/backends/fakenet/tests/fakenetworktest.h create mode 100644 solid/control/bluetoothinputdevice.cpp create mode 100644 solid/control/bluetoothinputdevice.h create mode 100644 solid/control/bluetoothinterface.cpp create mode 100644 solid/control/bluetoothinterface.h create mode 100644 solid/control/bluetoothmanager.cpp create mode 100644 solid/control/bluetoothmanager.h create mode 100644 solid/control/bluetoothremotedevice.cpp create mode 100644 solid/control/bluetoothremotedevice.h create mode 100644 solid/control/bluetoothsecurity.cpp create mode 100644 solid/control/bluetoothsecurity.h create mode 100644 solid/control/frontendobject.cpp create mode 100644 solid/control/frontendobject_p.h create mode 100644 solid/control/ifaces/CMakeLists.txt create mode 100644 solid/control/ifaces/authentication.cpp create mode 100644 solid/control/ifaces/authentication.h create mode 100644 solid/control/ifaces/bluetoothinputdevice.cpp create mode 100644 solid/control/ifaces/bluetoothinputdevice.h create mode 100644 solid/control/ifaces/bluetoothinterface.cpp create mode 100644 solid/control/ifaces/bluetoothinterface.h create mode 100644 solid/control/ifaces/bluetoothmanager.cpp create mode 100644 solid/control/ifaces/bluetoothmanager.h create mode 100644 solid/control/ifaces/bluetoothremotedevice.cpp create mode 100644 solid/control/ifaces/bluetoothremotedevice.h create mode 100644 solid/control/ifaces/bluetoothsecurity.cpp create mode 100644 solid/control/ifaces/bluetoothsecurity.h create mode 100644 solid/control/ifaces/networkcdmainterface.cpp create mode 100644 solid/control/ifaces/networkcdmainterface.h create mode 100644 solid/control/ifaces/networkgsminterface.cpp create mode 100644 solid/control/ifaces/networkgsminterface.h create mode 100644 solid/control/ifaces/networkinterface.cpp create mode 100644 solid/control/ifaces/networkinterface.h create mode 100644 solid/control/ifaces/networkmanager.cpp create mode 100644 solid/control/ifaces/networkmanager.h create mode 100644 solid/control/ifaces/networkserialinterface.cpp create mode 100644 solid/control/ifaces/networkserialinterface.h create mode 100644 solid/control/ifaces/powermanager.cpp create mode 100644 solid/control/ifaces/powermanager.h create mode 100644 solid/control/ifaces/wirednetworkinterface.cpp create mode 100644 solid/control/ifaces/wirednetworkinterface.h create mode 100644 solid/control/ifaces/wirelessaccesspoint.cpp create mode 100644 solid/control/ifaces/wirelessaccesspoint.h create mode 100644 solid/control/ifaces/wirelessnetworkinterface.cpp create mode 100644 solid/control/ifaces/wirelessnetworkinterface.h create mode 100644 solid/control/managerbase.cpp create mode 100644 solid/control/managerbase_p.h create mode 100644 solid/control/network_p.h create mode 100644 solid/control/networkcdmainterface.cpp create mode 100644 solid/control/networkcdmainterface.h create mode 100644 solid/control/networkcdmainterface_p.h create mode 100644 solid/control/networkgsminterface.cpp create mode 100644 solid/control/networkgsminterface.h create mode 100644 solid/control/networkgsminterface_p.h create mode 100644 solid/control/networking.cpp create mode 100644 solid/control/networking.h create mode 100644 solid/control/networking_p.h create mode 100644 solid/control/networkinterface.cpp create mode 100644 solid/control/networkinterface.h create mode 100644 solid/control/networkinterface_p.h create mode 100644 solid/control/networkipv4config.cpp create mode 100644 solid/control/networkipv4config.h create mode 100644 solid/control/networkmanager.cpp create mode 100644 solid/control/networkmanager.h create mode 100644 solid/control/networkmanager_p.h create mode 100644 solid/control/networkserialinterface.cpp create mode 100644 solid/control/networkserialinterface.h create mode 100644 solid/control/networkserialinterface_p.h create mode 100644 solid/control/org.kde.Solid.Networking.xml create mode 100644 solid/control/powermanager.cpp create mode 100644 solid/control/powermanager.h create mode 100644 solid/control/powermanager_p.h create mode 100644 solid/control/singletondefs.h create mode 100644 solid/control/solid_control_export.h create mode 100644 solid/control/solidbluetoothmanager.desktop create mode 100644 solid/control/soliddefs_p.h create mode 100644 solid/control/solidnetworkmanager.desktop create mode 100644 solid/control/solidpowermanager.desktop create mode 100644 solid/control/tests/CMakeLists.txt create mode 100644 solid/control/tests/solidbluetoothtest.cpp create mode 100644 solid/control/tests/solidbluetoothtest.h create mode 100644 solid/control/tests/solidnettest.cpp create mode 100644 solid/control/tests/solidnettest.h create mode 100644 solid/control/wirednetworkinterface.cpp create mode 100644 solid/control/wirednetworkinterface.h create mode 100644 solid/control/wirednetworkinterface_p.h create mode 100644 solid/control/wirelessaccesspoint.cpp create mode 100644 solid/control/wirelessaccesspoint.h create mode 100644 solid/control/wirelessnetworkinterface.cpp create mode 100644 solid/control/wirelessnetworkinterface.h create mode 100644 solid/control/wirelessnetworkinterface_p.h create mode 100644 taskmanager/CMakeLists.txt create mode 100644 taskmanager/Mainpage.dox create mode 100644 taskmanager/Messages.sh create mode 100644 taskmanager/abstractgroupableitem.cpp create mode 100644 taskmanager/abstractgroupableitem.h create mode 100644 taskmanager/abstractgroupingstrategy.cpp create mode 100644 taskmanager/abstractgroupingstrategy.h create mode 100644 taskmanager/abstractsortingstrategy.cpp create mode 100644 taskmanager/abstractsortingstrategy.h create mode 100644 taskmanager/groupmanager.cpp create mode 100644 taskmanager/groupmanager.h create mode 100644 taskmanager/startup.cpp create mode 100644 taskmanager/startup.h create mode 100644 taskmanager/strategies/alphasortingstrategy.cpp create mode 100644 taskmanager/strategies/alphasortingstrategy.h create mode 100644 taskmanager/strategies/manualgroupingstrategy.cpp create mode 100644 taskmanager/strategies/manualgroupingstrategy.h create mode 100644 taskmanager/strategies/manualsortingstrategy.cpp create mode 100644 taskmanager/strategies/manualsortingstrategy.h create mode 100644 taskmanager/strategies/programgroupingstrategy.cpp create mode 100644 taskmanager/strategies/programgroupingstrategy.h create mode 100644 taskmanager/task.cpp create mode 100644 taskmanager/task.h create mode 100644 taskmanager/taskactions.cpp create mode 100644 taskmanager/taskactions.h create mode 100644 taskmanager/taskactions_p.h create mode 100644 taskmanager/taskgroup.cpp create mode 100644 taskmanager/taskgroup.h create mode 100644 taskmanager/taskitem.cpp create mode 100644 taskmanager/taskitem.h create mode 100644 taskmanager/taskmanager.cpp create mode 100644 taskmanager/taskmanager.h create mode 100644 taskmanager/taskmanager_export.h create mode 100644 taskmanager/taskmanager_p.h create mode 100644 taskmanager/taskrmbmenu.cpp create mode 100644 taskmanager/taskrmbmenu.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 8c850b99b..ea47957f6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,299 +1,14 @@ -find_package(Nepomuk REQUIRED) -include (KDE4Defaults) -include(NepomukMacros) - -include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${KDEBASE_WORKSPACE_SOURCE_DIR}/libs ${CMAKE_CURRENT_SOURCE_DIR}/.. ${KDE4_INCLUDES}) -if(QT_QTOPENGL_FOUND AND OPENGL_FOUND) - include_directories(${OPENGL_INCLUDE_DIR}) -endif(QT_QTOPENGL_FOUND AND OPENGL_FOUND) - -add_subdirectory(tests) -add_definitions(-DKDE_DEFAULT_DEBUG_AREA=1209) - -########### next target ############### - -set(plasmagik_SRCS - packagemetadata.cpp - packagestructure.cpp - package.cpp - ) - -set(plasma_LIB_SRCS - ${plasmagik_SRCS} - abstractrunner.cpp - animationdriver.cpp - animator.cpp - applet.cpp - configloader.cpp - containment.cpp - context.cpp - corona.cpp - datacontainer.cpp - dataengine.cpp - dataenginemanager.cpp - delegate.cpp - dialog.cpp - extender.cpp - extenderitem.cpp - paintutils.cpp - framesvg.cpp - plasma.cpp - popupapplet.cpp - private/applethandle.cpp - private/datacontainer_p.cpp - private/desktoptoolbox.cpp - private/extenderapplet.cpp - private/nativetabbar.cpp - private/packages.cpp - private/paneltoolbox.cpp - private/style.cpp - private/toolbox.cpp - private/tooltip.cpp - private/windowpreview.cpp - querymatch.cpp - runnercontext.cpp - runnermanager.cpp - scripting/appletscript.cpp - scripting/dataenginescript.cpp - scripting/runnerscript.cpp - scripting/scriptengine.cpp - scripting/uiloader.cpp - service.cpp - servicejob.cpp - svg.cpp - theme.cpp - tooltipcontent.cpp - tooltipmanager.cpp - version.cpp - view.cpp - wallpaper.cpp - widgets/checkbox.cpp - widgets/combobox.cpp - widgets/flashinglabel.cpp - widgets/frame.cpp - widgets/groupbox.cpp - widgets/iconwidget.cpp - widgets/label.cpp - widgets/lineedit.cpp - widgets/meter.cpp - widgets/pushbutton.cpp - widgets/radiobutton.cpp - widgets/scrollbar.cpp - widgets/signalplotter.cpp - widgets/slider.cpp - widgets/busywidget.cpp - widgets/svgwidget.cpp - widgets/tabbar.cpp - widgets/treeview.cpp - widgets/textedit.cpp - widgets/webview.cpp -) - -#NEPOMUK_GENERATE_FROM_ONTOLOGY( -# nwc.nrl -# ${metadata_test_BINARY_DIR} -# TEST_HEADERS -# TEST_SOURCES -# TEST_INCLUDES -#) - -if(QT_QTOPENGL_FOUND AND OPENGL_FOUND) -MESSAGE(STATUS "Adding support for OpenGL applets to libplasma") -set(plasma_LIB_SRCS - ${plasma_LIB_SRCS} - glapplet.cpp) -endif(QT_QTOPENGL_FOUND AND OPENGL_FOUND) - -kde4_add_library(plasma SHARED ${plasma_LIB_SRCS}) - -target_link_libraries(plasma ${KDE4_KIO_LIBS} ${KDE4_KFILE_LIBS} ${KDE4_KNEWSTUFF2_LIBS} - ${QT_QTUITOOLS_LIBRARY} ${QT_QTWEBKIT_LIBRARY} - ${KDE4_THREADWEAVER_LIBRARIES} ${KDE4_SOLID_LIBS} ${X11_LIBRARIES}) -if(DL_LIBRARY) -target_link_libraries(plasma ${DL_LIBRARY}) -endif(DL_LIBRARY) - -if(QT_QTOPENGL_FOUND AND OPENGL_FOUND) - target_link_libraries(plasma ${QT_QTOPENGL_LIBRARY} ${OPENGL_gl_LIBRARY}) -endif(QT_QTOPENGL_FOUND AND OPENGL_FOUND) - -set_target_properties(plasma PROPERTIES - VERSION 3.0.0 - SOVERSION 3 - ${KDE4_DISABLE_PROPERTY_}LINK_INTERFACE_LIBRARIES "${KDE4_KDEUI_LIBS}" - ) - -install(TARGETS plasma ${INSTALL_TARGETS_DEFAULT_ARGS}) - - -########### install files ############### - -set(plasmagik_HEADERS - packagemetadata.h - packagestructure.h - package.h - ) - -install(FILES ${plasmagik_HEADERS} DESTINATION ${INCLUDE_INSTALL_DIR}/plasma/ COMPONENT Devel) - -set(plasma_LIB_INCLUDES - abstractrunner.h - animationdriver.h - animator.h - applet.h - configloader.h - containment.h - context.h - corona.h - datacontainer.h - dataengine.h - dataenginemanager.h - delegate.h - dialog.h - extender.h - extenderitem.h - paintutils.h - framesvg.h - plasma.h - plasma_export.h - popupapplet.h - querymatch.h - runnercontext.h - runnermanager.h - service.h - servicejob.h - svg.h - theme.h - tooltipcontent.h - tooltipmanager.h - tooltipmanager.h - version.h - view.h - wallpaper.h) - -if(QT_QTOPENGL_FOUND AND OPENGL_FOUND) -set(plasma_LIB_INCLUDES - ${plasma_LIB_INCLUDES} - glapplet.h) -endif(QT_QTOPENGL_FOUND AND OPENGL_FOUND) - -install(FILES - ${plasma_LIB_INCLUDES} - DESTINATION ${INCLUDE_INSTALL_DIR}/plasma COMPONENT Devel) - -install(FILES - widgets/checkbox.h - widgets/combobox.h - widgets/flashinglabel.h - widgets/frame.h - widgets/groupbox.h - widgets/iconwidget.h - widgets/label.h - widgets/lineedit.h - widgets/meter.h - widgets/pushbutton.h - widgets/radiobutton.h - widgets/scrollbar.h - widgets/signalplotter.h - widgets/slider.h - widgets/busywidget.h - widgets/svgwidget.h - widgets/tabbar.h - widgets/treeview.h - widgets/textedit.h - widgets/webview.h - DESTINATION ${INCLUDE_INSTALL_DIR}/plasma/widgets COMPONENT Devel) - -install(FILES - scripting/appletscript.h - scripting/dataenginescript.h - scripting/runnerscript.h - scripting/scriptengine.h - scripting/uiloader.h - DESTINATION ${INCLUDE_INSTALL_DIR}/plasma/scripting COMPONENT Devel) - - -install(FILES -includes/AbstractRunner -includes/AnimationDriver -includes/Animator -includes/Applet -includes/AppletScript -includes/CheckBox -includes/ComboBox -includes/ConfigLoader -includes/Containment -includes/Context -includes/Corona -includes/DataContainer -includes/DataEngine -includes/DataEngineManager -includes/DataEngineScript -includes/Delegate -includes/Dialog -includes/Extender -includes/ExtenderItem -includes/FlashingLabel -includes/Frame -includes/FrameSvg -includes/GroupBox -includes/IconWidget -includes/Label -includes/LineEdit -includes/Meter -includes/Package -includes/PackageMetadata -includes/PackageStructure -includes/PaintUtils -includes/Plasma -includes/PopupApplet -includes/PushButton -includes/QueryMatch -includes/RadioButton -includes/RunnerContext -includes/RunnerManager -includes/RunnerScript -includes/ScriptEngine -includes/ScrollBar -includes/Service -includes/ServiceJob -includes/SignalPlotter -includes/Slider -includes/BusyWidget -includes/Svg -includes/SvgWidget -includes/TabBar -includes/TextEdit -includes/ToolTipManager -includes/Theme -includes/TreeView -includes/UiLoader -includes/View -includes/Version -includes/Wallpaper -includes/WebView -DESTINATION ${INCLUDE_INSTALL_DIR}/KDE/Plasma COMPONENT Devel) - -if(QT_QTOPENGL_FOUND AND OPENGL_FOUND) - install(FILES - includes/GLApplet - DESTINATION ${INCLUDE_INSTALL_DIR}/KDE/Plasma COMPONENT Devel) -endif(QT_QTOPENGL_FOUND AND OPENGL_FOUND) - -install(FILES - servicetypes/plasma-animator.desktop - servicetypes/plasma-applet.desktop - servicetypes/plasma-containment.desktop - servicetypes/plasma-dataengine.desktop - servicetypes/plasma-packagestructure.desktop - servicetypes/plasma-runner.desktop - servicetypes/plasma-scriptengine.desktop - servicetypes/plasma-wallpaper.desktop - DESTINATION ${SERVICETYPES_INSTALL_DIR}) - -install(FILES - servicetypes/plasma-applet-extenderapplet.desktop - DESTINATION ${SERVICES_INSTALL_DIR}) - -install(FILES scripting/plasmoids.knsrc DESTINATION ${CONFIG_INSTALL_DIR}) +add_subdirectory(kdm) +add_subdirectory(solid) +add_subdirectory(plasma) +add_subdirectory(libplasmaclock) +if(NOT WIN32) + add_subdirectory(taskmanager) + add_subdirectory(ksysguard) + add_subdirectory(kworkspace) +endif(NOT WIN32) +if(Nepomuk_FOUND) + add_subdirectory(nepomukquery) + add_subdirectory(nepomukqueryclient) +endif(Nepomuk_FOUND) diff --git a/Mainpage.dox b/Mainpage.dox index 225e338fb..9e107d1ee 100644 --- a/Mainpage.dox +++ b/Mainpage.dox @@ -1,100 +1,16 @@ -/** @mainpage Plasma libraries +/** @mainpage KDE Workspace Libraries -libplasma is the core of the Plasma desktop. It provides a framework of graphical -widgets (Plasma::Applet) that can be organised into managed groupings -(Plasma::Containment), such as a desktop or panel. It also provides a data -abstraction layer (Plasma::DataEngine) and a corresponding service interaction -layer (Plasma::Service) to make implementing widgets easier and a -system of callouts (Plasma::AbstractRunner) that provide responses to queries, -from running an application to performing a quick calculation. +Libraries for the KDE workspace. +

+The following libraries are available: +- libplasma, a library for implementing + %Plasma applets and data engines +- libkworkspace, a library for + interacting with the workspace -The Qt Graphics View -framework and the KDE -libraries provide the underpinning for libplasma. As a result, it should -work anywhere that Qt and KDE do. - -Although libplasma is developed for the use of Plasma, the new desktop shell in -KDE 4, it is general enough to be useful in other applications. -Amarok is already using it for its context -view, allowing for pluggable widgets to display and interact with the music -collection, such as "current track" and "tag cloud" widgets. - -libplasma itself only provides a framework, and the widgets, containments, -data engines and runners are all implemented as plugins. However, the framework -is designed to make implementing these plugins as easy as possible, including -providing scripting support. Also, infrastructure such as a dialog to install -new widgets and even download them from the web (Plasma::AppletBrowser) is also -included. - -Other important classes are: - - - Plasma::Corona: the canvas that containments are placed on - - Plasma::View: a QWidget for displaying a containment - - Plasma::Theme: provides theming support - - Plasma::Animator: provides animations for things like elements appearing - and disappearing - - Plasma::Delegate: provides an item delegate for Qt's - Model / - View framework for menu items. - - Plasma::ToolTipManager: allows widgets have (themed) tooltips displayed when the - mouse is hovered over them - - Plasma::Dialog: displays a themed application dialog - - Plasma::Extender: provides detachable sections to Plasma::Applet - - Plasma::GLApplet: provides an OpneGL-rendered Plasma::Applet - - Plasma::PackageStructure: provides descriptions of packages containing plugins - for libplasma - - Plasma::PopupApplet: provides a simple way of implementing a Plasma::Applet - consisting of an icon that shows a popup when clicked - - Plasma::Svg and Plasma::FrameSvg: provides themable, cached SVGs - - Plasma::Wallpaper: provides pluggable backgrounds for containments - - Plasma::AppletScript, Plasma::DataEngineScript, Plasma::RunnerScript and - Plasma::ScriptEngine: provide scripting interfaces for plugins - - Various themed QGraphicsWidgets for use in creating a Plasma::Applet - - -The -Plasma tutorials -on TechBase provide a good introduction to writing plugins, such as widgets and -data engines, for libplasma-based applications. - -@authors -Aaron Seigo \
-Alessandro Diaferia \
-Alex Merry \
-Alexander Wiedenbruch \
-Alexis Ménard \
-André Duffeck \
-Andrew Lake \
-Bertjan Broeksema \
-Chani Armitage \
-Davide Bettio \
-Dan Meltzer \
-Fredrik Höglund \
-Ivan Cukic \
-John Tapsell \
-Jordi Polo \
-Kevin Ottens \
-Montel Laurent \ -Marco Martin \
-Matt Broadstone \
-Petri Damsten \
-Rafael Fernández López \
-Riccardo Iaconelli \
-Richard J. Moore \
-Rob Scheepmaker \
-Robert Knight \
-Sebastian Kuegler \
-Siraj Razick \
-Zack Rusin \ - -@maintainers -Aaron Seigo \ - -@licenses -@lgpl +In addition, two KDM plugins are provided. */ -// DOXYGEN_SET_PROJECT_NAME = libplasma -// DOXYGEN_SET_RECURSIVE = YES +// DOXYGEN_SET_PROJECT_NAME = Libraries // vim:ts=4:sw=4:expandtab:filetype=doxygen diff --git a/kdm/CMakeLists.txt b/kdm/CMakeLists.txt new file mode 100644 index 000000000..e3aa78734 --- /dev/null +++ b/kdm/CMakeLists.txt @@ -0,0 +1,47 @@ + +include_directories( ${KDEBASE_WORKSPACE_SOURCE_DIR}/kdm/kfrontend ) + +########### next target ############### + +set(kgreet_classic_PART_SRCS kgreet_classic.cpp ) + + +kde4_add_plugin(kgreet_classic ${kgreet_classic_PART_SRCS}) + + +target_link_libraries(kgreet_classic ${KDE4_KDEUI_LIBS}) + +install(TARGETS kgreet_classic DESTINATION ${PLUGIN_INSTALL_DIR} ) + + +########### next target ############### + +set(kgreet_winbind_PART_SRCS kgreet_winbind.cpp ) + + +kde4_add_plugin(kgreet_winbind ${kgreet_winbind_PART_SRCS}) + + +target_link_libraries(kgreet_winbind ${KDE4_KDEUI_LIBS}) + +install(TARGETS kgreet_winbind DESTINATION ${PLUGIN_INSTALL_DIR} ) + +########### next target ############### + +set(kgreet_generic_PART_SRCS kgreet_generic.cpp ) + + +kde4_add_plugin(kgreet_generic ${kgreet_generic_PART_SRCS}) + + +target_link_libraries(kgreet_generic ${KDE4_KDEUI_LIBS}) + +install(TARGETS kgreet_generic DESTINATION ${PLUGIN_INSTALL_DIR} ) + + + + + +########### install files ############### + +install( FILES kgreeterplugin.h DESTINATION ${INCLUDE_INSTALL_DIR} COMPONENT Devel ) diff --git a/kdm/Messages.sh b/kdm/Messages.sh new file mode 100644 index 000000000..be2077f45 --- /dev/null +++ b/kdm/Messages.sh @@ -0,0 +1,4 @@ +#! /usr/bin/env bash +$XGETTEXT kgreet_classic.cpp -o $podir/kgreet_classic.pot +$XGETTEXT kgreet_winbind.cpp -o $podir/kgreet_winbind.pot +$XGETTEXT kgreet_generic.cpp -o $podir/kgreet_generic.pot diff --git a/kdm/kgreet_classic.cpp b/kdm/kgreet_classic.cpp new file mode 100644 index 000000000..fa0b9b86b --- /dev/null +++ b/kdm/kgreet_classic.cpp @@ -0,0 +1,484 @@ +/* + +Conversation widget for kdm greeter + +Copyright (C) 1997, 1998, 2000 Steffen Hansen +Copyright (C) 2000-2003 Oswald Buddenhagen + + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +#include "kgreet_classic.h" +#include "themer/kdmthemer.h" +#include "themer/kdmitem.h" + +#include +#include +#include +#include + +#include +#include +#include + +static int echoMode; + +class KDMPasswordEdit : public KLineEdit { +public: + KDMPasswordEdit( QWidget *parent ) : KLineEdit( parent ) + { + if (::echoMode == -1) + setPasswordMode(true); + else + setEchoMode( ::echoMode ? Password : NoEcho ); + setContextMenuPolicy( Qt::NoContextMenu ); + } +}; + +KClassicGreeter::KClassicGreeter( KGreeterPluginHandler *_handler, + QWidget *parent, + const QString &_fixedEntity, + Function _func, Context _ctx ) : + QObject(), + KGreeterPlugin( _handler ), + fixedUser( _fixedEntity ), + func( _func ), + ctx( _ctx ), + exp( -1 ), + pExp( -1 ), + running( false ) +{ + QGridLayout *grid = 0; + int line = 0; + + if (!_handler->gplugHasNode( "user-entry" ) || + !_handler->gplugHasNode( "pw-entry" )) + { + parent = new QWidget( parent ); + parent->setObjectName( "talker" ); + widgetList << parent; + grid = new QGridLayout( parent ); + grid->setMargin( 0 ); + } + + loginLabel = passwdLabel = passwd1Label = passwd2Label = 0; + loginEdit = 0; + passwdEdit = passwd1Edit = passwd2Edit = 0; + if (ctx == ExUnlock || ctx == ExChangeTok) + fixedUser = KUser().loginName(); + if (func != ChAuthTok) { + if (fixedUser.isEmpty()) { + loginEdit = new KLineEdit( parent ); + loginEdit->setContextMenuPolicy( Qt::NoContextMenu ); + connect( loginEdit, SIGNAL(editingFinished()), SLOT(slotLoginLostFocus()) ); + connect( loginEdit, SIGNAL(editingFinished()), SLOT(slotChanged()) ); + connect( loginEdit, SIGNAL(textChanged( const QString & )), SLOT(slotChanged()) ); + connect( loginEdit, SIGNAL(selectionChanged()), SLOT(slotChanged()) ); + if (!grid) { + loginEdit->setObjectName( "user-entry" ); + widgetList << loginEdit; + } else { + loginLabel = new QLabel( i18n("&Username:"), parent ); + loginLabel->setBuddy( loginEdit ); + grid->addWidget( loginLabel, line, 0 ); + grid->addWidget( loginEdit, line++, 1 ); + } + } else if (ctx != Login && ctx != Shutdown && grid) { + loginLabel = new QLabel( i18n("Username:"), parent ); + grid->addWidget( loginLabel, line, 0 ); + grid->addWidget( new QLabel( fixedUser, parent ), line++, 1 ); + } + passwdEdit = new KDMPasswordEdit( parent ); + connect( passwdEdit, SIGNAL(textChanged( const QString & )), + SLOT(slotChanged()) ); + connect( passwdEdit, SIGNAL(editingFinished()), SLOT(slotChanged()) ); + if (!grid) { + passwdEdit->setObjectName( "pw-entry" ); + widgetList << passwdEdit; + } else { + passwdLabel = new QLabel( func == Authenticate ? + i18n("&Password:") : + i18n("Current &password:"), + parent ); + passwdLabel->setBuddy( passwdEdit ); + grid->addWidget( passwdLabel, line, 0 ); + grid->addWidget( passwdEdit, line++, 1 ); + } + if (loginEdit) + loginEdit->setFocus(); + else + passwdEdit->setFocus(); + } + if (func != Authenticate) { + passwd1Edit = new KDMPasswordEdit( parent ); + passwd1Label = new QLabel( i18n("&New password:"), parent ); + passwd1Label->setBuddy( passwd1Edit ); + passwd2Edit = new KDMPasswordEdit( parent ); + passwd2Label = new QLabel( i18n("Con&firm password:"), parent ); + passwd2Label->setBuddy( passwd2Edit ); + if (grid) { + grid->addWidget( passwd1Label, line, 0 ); + grid->addWidget( passwd1Edit, line++, 1 ); + grid->addWidget( passwd2Label, line, 0 ); + grid->addWidget( passwd2Edit, line, 1 ); + } + if (!passwdEdit) + passwd1Edit->setFocus(); + } +} + +// virtual +KClassicGreeter::~KClassicGreeter() +{ + abort(); + qDeleteAll( widgetList ); +} + +void // virtual +KClassicGreeter::loadUsers( const QStringList &users ) +{ + KCompletion *userNamesCompletion = new KCompletion; + userNamesCompletion->setItems( users ); + loginEdit->setCompletionObject( userNamesCompletion ); + loginEdit->setAutoDeleteCompletionObject( true ); + loginEdit->setCompletionMode( KGlobalSettings::CompletionAuto ); +} + +void // virtual +KClassicGreeter::presetEntity( const QString &entity, int field ) +{ + loginEdit->setText( entity ); + if (field == 1) + passwdEdit->setFocus(); + else { + loginEdit->setFocus(); + loginEdit->selectAll(); + if (field == -1) { + passwdEdit->setText( " " ); + passwdEdit->setEnabled( false ); + authTok = false; + } + } + curUser = entity; +} + +QString // virtual +KClassicGreeter::getEntity() const +{ + return fixedUser.isEmpty() ? loginEdit->text() : fixedUser; +} + +void // virtual +KClassicGreeter::setUser( const QString &user ) +{ + // assert( fixedUser.isEmpty() ); + curUser = user; + loginEdit->setText( user ); + passwdEdit->setFocus(); + passwdEdit->selectAll(); +} + +void // virtual +KClassicGreeter::setEnabled( bool enable ) +{ + // assert( !passwd1Label ); + // assert( func == Authenticate && ctx == Shutdown ); +// if (loginLabel) +// loginLabel->setEnabled( enable ); + passwdLabel->setEnabled( enable ); + setActive( enable ); + if (enable) + passwdEdit->setFocus(); +} + +void // private +KClassicGreeter::returnData() +{ + switch (exp) { + case 0: + handler->gplugReturnText( (loginEdit ? loginEdit->text() : + fixedUser).toLocal8Bit(), + KGreeterPluginHandler::IsUser ); + break; + case 1: + Q_ASSERT(passwdEdit); + handler->gplugReturnText( passwdEdit->text().toLocal8Bit() , + KGreeterPluginHandler::IsPassword | + KGreeterPluginHandler::IsSecret ); + break; + case 2: + Q_ASSERT(passwd1Edit); + handler->gplugReturnText( passwd1Edit->text().toLocal8Bit(), + KGreeterPluginHandler::IsSecret ); + break; + default: // case 3: + Q_ASSERT(passwd2Edit); + handler->gplugReturnText( passwd2Edit->text().toLocal8Bit(), + KGreeterPluginHandler::IsNewPassword | + KGreeterPluginHandler::IsSecret ); + break; + } +} + +bool // virtual +KClassicGreeter::textMessage( const char *text, bool err ) +{ + if (!err && + QString( text ).indexOf( QRegExp( "^Changing password for [^ ]+$" ) ) >= 0) + return true; + return false; +} + +void // virtual +KClassicGreeter::textPrompt( const char *prompt, bool echo, bool nonBlocking ) +{ + pExp = exp; + if (echo) + exp = 0; + else if (!authTok) + exp = 1; + else { + QString pr( prompt ); + if (pr.indexOf( QRegExp( "\\bpassword\\b", Qt::CaseInsensitive ) ) >= 0) { + if (pr.indexOf( QRegExp( "\\b(re-?(enter|type)|again|confirm|repeat)\\b", + Qt::CaseInsensitive ) ) >= 0) + exp = 3; + else if (pr.indexOf( QRegExp( "\\bnew\\b", Qt::CaseInsensitive ) ) >= 0) + exp = 2; + else { // QRegExp( "\\b(old|current)\\b", Qt::CaseInsensitive ) is too strict + handler->gplugReturnText( "", + KGreeterPluginHandler::IsOldPassword | + KGreeterPluginHandler::IsSecret ); + return; + } + } else { + handler->gplugMsgBox( QMessageBox::Critical, + i18n("Unrecognized prompt \"%1\"", + prompt ) ); + handler->gplugReturnText( 0, 0 ); + exp = -1; + return; + } + } + + if (pExp >= 0 && pExp >= exp) { + revive(); + has = -1; + } + + if (has >= exp || nonBlocking) + returnData(); +} + +bool // virtual +KClassicGreeter::binaryPrompt( const char *, bool ) +{ + // this simply cannot happen ... :} + return true; +} + +void // virtual +KClassicGreeter::start() +{ + authTok = !(passwdEdit && passwdEdit->isEnabled()); + exp = has = -1; + running = true; +} + +void // virtual +KClassicGreeter::suspend() +{ +} + +void // virtual +KClassicGreeter::resume() +{ +} + +void // virtual +KClassicGreeter::next() +{ + // assert( running ); + if (loginEdit && loginEdit->hasFocus()) { + passwdEdit->setFocus(); // will cancel running login if necessary + has = 0; + } else if (passwdEdit && passwdEdit->hasFocus()) { + if (passwd1Edit) + passwd1Edit->setFocus(); + has = 1; + } else if (passwd1Edit) { + if (passwd1Edit->hasFocus()) { + passwd2Edit->setFocus(); + has = 1; // sic! + } else + has = 3; + } else + has = 1; + if (exp < 0) + handler->gplugStart(); + else if (has >= exp) + returnData(); +} + +void // virtual +KClassicGreeter::abort() +{ + running = false; + if (exp >= 0) { + exp = -1; + handler->gplugReturnText( 0, 0 ); + } +} + +void // virtual +KClassicGreeter::succeeded() +{ + // assert( running || timed_login ); + if (!authTok) { + setActive( false ); + if (passwd1Edit) { + authTok = true; + return; + } + } else + setActive2( false ); + exp = -1; + running = false; +} + +void // virtual +KClassicGreeter::failed() +{ + // assert( running || timed_login ); + setActive( false ); + setActive2( false ); + exp = -1; + running = false; +} + +void // virtual +KClassicGreeter::revive() +{ + // assert( !running ); + setActive2( true ); + if (authTok) { + passwd1Edit->clear(); + passwd2Edit->clear(); + passwd1Edit->setFocus(); + } else { + passwdEdit->clear(); + if (loginEdit && loginEdit->isEnabled()) + passwdEdit->setEnabled( true ); + else { + setActive( true ); + if (loginEdit && loginEdit->text().isEmpty()) + loginEdit->setFocus(); + else + passwdEdit->setFocus(); + } + } +} + +void // virtual +KClassicGreeter::clear() +{ + // assert( !running && !passwd1Edit ); + passwdEdit->clear(); + if (loginEdit) { + loginEdit->clear(); + loginEdit->setFocus(); + curUser.clear(); + } else + passwdEdit->setFocus(); +} + + +// private + +void +KClassicGreeter::setActive( bool enable ) +{ + if (loginEdit) + loginEdit->setEnabled( enable ); + if (passwdEdit) + passwdEdit->setEnabled( enable ); +} + +void +KClassicGreeter::setActive2( bool enable ) +{ + if (passwd1Edit) { + passwd1Edit->setEnabled( enable ); + passwd2Edit->setEnabled( enable ); + } +} + +void +KClassicGreeter::slotLoginLostFocus() +{ + if (!running) + return; + if (exp > 0) { + if (curUser == loginEdit->text()) + return; + exp = -1; + handler->gplugReturnText( 0, 0 ); + } + curUser = loginEdit->text(); + handler->gplugSetUser( curUser ); +} + +void +KClassicGreeter::slotChanged() +{ + if (running) + handler->gplugChanged(); +} + +// factory + +static bool init( const QString &, + QVariant (*getConf)( void *, const char *, const QVariant & ), + void *ctx ) +{ + echoMode = getConf( ctx, "EchoPasswd", QVariant( -1 ) ).toInt(); + KGlobal::locale()->insertCatalog( "kgreet_classic" ); + return true; +} + +static void done( void ) +{ + KGlobal::locale()->removeCatalog( "kgreet_classic" ); +} + +static KGreeterPlugin * +create( KGreeterPluginHandler *handler, + QWidget *parent, + const QString &fixedEntity, + KGreeterPlugin::Function func, + KGreeterPlugin::Context ctx ) +{ + return new KClassicGreeter( handler, parent, fixedEntity, func, ctx ); +} + +KDE_EXPORT KGreeterPluginInfo kgreeterplugin_info = { + I18N_NOOP2("@item:inmenu authentication method", "Username + password (classic)"), "classic", + KGreeterPluginInfo::Local | KGreeterPluginInfo::Presettable, + init, done, create +}; + +#include "kgreet_classic.moc" diff --git a/kdm/kgreet_classic.h b/kdm/kgreet_classic.h new file mode 100644 index 000000000..946a777e9 --- /dev/null +++ b/kdm/kgreet_classic.h @@ -0,0 +1,84 @@ +/* + +Conversation widget for kdm greeter + +Copyright (C) 1997, 1998 Steffen Hansen +Copyright (C) 2000-2003 Oswald Buddenhagen + + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + + +#ifndef KGREET_CLASSIC_H +#define KGREET_CLASSIC_H + +#include "kgreeterplugin.h" + +#include + +class KLineEdit; +class KSimpleConfig; +class QLabel; + +class KClassicGreeter : public QObject, public KGreeterPlugin { + Q_OBJECT + + public: + KClassicGreeter( KGreeterPluginHandler *handler, + QWidget *parent, + const QString &fixedEntitiy, + Function func, Context ctx ); + ~KClassicGreeter(); + virtual void loadUsers( const QStringList &users ); + virtual void presetEntity( const QString &entity, int field ); + virtual QString getEntity() const; + virtual void setUser( const QString &user ); + virtual void setEnabled( bool on ); + virtual bool textMessage( const char *message, bool error ); + virtual void textPrompt( const char *prompt, bool echo, bool nonBlocking ); + virtual bool binaryPrompt( const char *prompt, bool nonBlocking ); + virtual void start(); + virtual void suspend(); + virtual void resume(); + virtual void next(); + virtual void abort(); + virtual void succeeded(); + virtual void failed(); + virtual void revive(); + virtual void clear(); + + public Q_SLOTS: + void slotLoginLostFocus(); + void slotChanged(); + + private: + void setActive( bool enable ); + void setActive2( bool enable ); + void returnData(); + + QLabel *loginLabel, *passwdLabel, *passwd1Label, *passwd2Label; + KLineEdit *loginEdit; + KLineEdit *passwdEdit, *passwd1Edit, *passwd2Edit; + KSimpleConfig *stsFile; + QString fixedUser, curUser; + Function func; + Context ctx; + int exp, pExp, has; + bool running, authTok; +}; + +#endif /* KGREET_CLASSIC_H */ diff --git a/kdm/kgreet_generic.cpp b/kdm/kgreet_generic.cpp new file mode 100644 index 000000000..f5b55e518 --- /dev/null +++ b/kdm/kgreet_generic.cpp @@ -0,0 +1,354 @@ +/* + +Conversation widget for kdm greeter + +Copyright (C) 2008 Dirk Mueller +Copyright (C) 2008 Oswald Buddenhagen + +based on classic kdm greeter: + + Copyright (C) 1997, 1998, 2000 Steffen Hansen + Copyright (C) 2000-2003 Oswald Buddenhagen + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +#include "kgreet_generic.h" + +#include +#include +#include +#include + +#include +#include +#include + +extern KDE_EXPORT KGreeterPluginInfo kgreeterplugin_info; // defined at bottom + +static int echoMode; + +class KDMPasswordEdit : public KLineEdit { +public: + KDMPasswordEdit( QWidget *parent = 0 ) : KLineEdit( parent ) + { + if (::echoMode == -1) + setPasswordMode( true ); + else + setEchoMode( ::echoMode ? Password : NoEcho ); + setContextMenuPolicy( Qt::NoContextMenu ); + } +}; + +KGenericGreeter::KGenericGreeter( KGreeterPluginHandler *_handler, + QWidget *parent, + const QString &_fixedEntity, + Function _func, Context _ctx ) : + QObject(), + KGreeterPlugin( _handler ), + m_lineEdit( 0 ), + fixedUser( _fixedEntity ), + func( _func ), + ctx( _ctx ), + exp( -1 ), + running( false ) +{ + m_parentWidget = new QWidget( parent ); + m_parentWidget->setObjectName( "talker" ); + // XXX set some minimal size + widgetList << m_parentWidget; + m_grid = new QGridLayout( m_parentWidget ); + m_grid->setMargin( 0 ); + + if (ctx == ExUnlock || ctx == ExChangeTok) + fixedUser = KUser().loginName(); +} + +// virtual +KGenericGreeter::~KGenericGreeter() +{ + abort(); + delete m_parentWidget; +} + +void // virtual +KGenericGreeter::loadUsers( const QStringList &users ) +{ + m_users = users; +} + +void // virtual +KGenericGreeter::presetEntity( const QString &entity, int /* field */ ) +{ + // assert( !running ); + curUser = entity; +} + +QString // virtual +KGenericGreeter::getEntity() const +{ + return fixedUser.isEmpty() ? curUser : fixedUser; +} + +void // virtual +KGenericGreeter::setUser( const QString &user ) +{ + // assert( running ); + // assert( fixedUser.isEmpty() ); + if (!(kgreeterplugin_info.flags & KGreeterPluginInfo::Presettable)) + return; // Not interested in PAM telling us who logged in + if (exp) { + abort(); + start(); + } + curUser = user; + if (m_lineEdit) { // could be null if plugin is misconfigured + m_lineEdit->setText( user ); + m_lineEdit->selectAll(); + m_lineEdit->setFocus(); + } +} + +void // virtual +KGenericGreeter::setEnabled( bool enable ) +{ + // assert( func == Authenticate && ctx == Shutdown ); + // XXX this is likely to bear some bogosity + foreach (QWidget *w, m_children) + w->setEnabled( enable ); + if (enable && m_lineEdit) + m_lineEdit->setFocus(); +} + +bool // virtual +KGenericGreeter::textMessage( const char *text, bool err ) +{ + if (err) + return false; + + if (m_infoMsgs.isEmpty()) + revive(); + QString qtext = QString::fromUtf8( text ); + m_infoMsgs.append( qtext ); + QLabel *label = new QLabel( qtext, m_parentWidget ); + m_grid->addWidget( label, m_line++, 0, 1, 2 ); + m_children.append( label ); + + return true; +} + +void // virtual +KGenericGreeter::textPrompt( const char *prompt, bool echo, bool /* nonBlocking */ ) +{ + exp = + exp >= 0 || + func != Authenticate || + !(kgreeterplugin_info.flags & KGreeterPluginInfo::Presettable); + + if (!exp && !fixedUser.isEmpty()) { + handler->gplugReturnText( fixedUser.toLocal8Bit(), + KGreeterPluginHandler::IsUser ); + return; + } + + if (m_infoMsgs.isEmpty()) + revive(); + else + m_infoMsgs.clear(); + + QLabel *label = new QLabel( QString::fromUtf8( prompt ).trimmed() ); + m_grid->addWidget( label, m_line, 0 ); + m_children.append( label ); + m_echo = echo; + if (echo) { + m_lineEdit = new KLineEdit; + m_lineEdit->setContextMenuPolicy( Qt::NoContextMenu ); + if (!exp) { + if (!m_users.isEmpty()) { + KCompletion *userNamesCompletion = new KCompletion; + userNamesCompletion->setItems( m_users ); + m_lineEdit->setCompletionObject( userNamesCompletion ); + m_lineEdit->setAutoDeleteCompletionObject( true ); + m_lineEdit->setCompletionMode( KGlobalSettings::CompletionAuto ); + } + if (!curUser.isEmpty()) { + m_lineEdit->setText( curUser ); + m_lineEdit->selectAll(); + connect( m_lineEdit, SIGNAL(selectionChanged()), SLOT(slotChanged()) ); + } + connect( m_lineEdit, SIGNAL(editingFinished()), SLOT(slotLoginLostFocus()) ); + } + connect( m_lineEdit, SIGNAL(editingFinished()), SLOT(slotChanged()) ); + connect( m_lineEdit, SIGNAL(textChanged( const QString & )), SLOT(slotChanged()) ); + } else { + m_lineEdit = new KDMPasswordEdit; + } + m_lineEdit->setMinimumWidth( + m_lineEdit->fontMetrics().width( "This is a long password" ) ); + m_grid->addWidget( m_lineEdit, m_line, 1 ); + m_children.append( m_lineEdit ); + m_lineEdit->show(); + m_lineEdit->setFocus(); +} + +bool // virtual +KGenericGreeter::binaryPrompt( const char *, bool ) +{ + // FIXME + return true; +} + +void // virtual +KGenericGreeter::start() +{ + exp = -1; + running = true; + handler->gplugStart(); +} + +void // virtual +KGenericGreeter::suspend() +{ +} + +void // virtual +KGenericGreeter::resume() +{ +} + +void // virtual +KGenericGreeter::next() +{ + if (m_lineEdit) { + m_lineEdit->setEnabled( false ); + QString text = m_lineEdit->text(); + m_lineEdit = 0; + handler->gplugReturnText( text.toLocal8Bit(), + !m_echo ? + KGreeterPluginHandler::IsSecret : + !exp ? + KGreeterPluginHandler::IsUser : 0 ); + } +} + +void // virtual +KGenericGreeter::abort() +{ + running = false; + if (exp >= 0) { + exp = -1; + handler->gplugReturnText( 0, 0 ); + } +} + +void // virtual +KGenericGreeter::succeeded() +{ + failed(); // redefining terms :-D +} + +void // virtual +KGenericGreeter::failed() +{ + // assert( running || timed_login ); + if (!m_infoMsgs.isEmpty()) { + QString text = ""; + foreach (const QString &msg, m_infoMsgs) + text += "

" + Qt::escape( msg ) + "

"; + text += ""; + revive(); + handler->gplugMsgBox( QMessageBox::Information, text ); + } else { + foreach (QWidget *w, m_children) + w->setEnabled( false ); + } + exp = -1; + running = false; +} + +void // virtual +KGenericGreeter::revive() +{ + // assert( !running ); + foreach (QWidget *w, m_children) + w->deleteLater(); + m_children.clear(); + m_infoMsgs.clear(); + m_lineEdit = 0; + m_line = 0; +} + +void // virtual +KGenericGreeter::clear() +{ + // assert( !running && !passwd1Edit ); + revive(); + curUser = QString::null; +} + + +// private +void +KGenericGreeter::slotLoginLostFocus() +{ + if (curUser != m_lineEdit->text()) { + curUser = m_lineEdit->text(); + handler->gplugSetUser( curUser ); + } +} + +void +KGenericGreeter::slotChanged() +{ + handler->gplugChanged(); +} + +// factory +static bool init( const QString &, + QVariant (*getConf)( void *, const char *, const QVariant & ), + void *ctx ) +{ + echoMode = getConf( ctx, "EchoMode", QVariant( -1 ) ).toInt(); + // Fielded entities are not supported per se. + // This implies that the first field is the presettable entity, if any. + if (getConf( ctx, "generic.Presettable", QVariant( false ) ).toBool()) + kgreeterplugin_info.flags |= KGreeterPluginInfo::Presettable; + KGlobal::locale()->insertCatalog( "kgreet_generic" ); + return true; +} + +static void done( void ) +{ + KGlobal::locale()->removeCatalog( "kgreet_generic" ); +} + +static KGreeterPlugin * +create( KGreeterPluginHandler *handler, + QWidget *parent, + const QString &fixedEntity, + KGreeterPlugin::Function func, + KGreeterPlugin::Context ctx ) +{ + return new KGenericGreeter( handler, parent, fixedEntity, func, ctx ); +} + +KDE_EXPORT KGreeterPluginInfo kgreeterplugin_info = { + I18N_NOOP2("@item:inmenu authentication method", "Generic"), "generic", + KGreeterPluginInfo::Local, + init, done, create +}; + +#include "kgreet_generic.moc" diff --git a/kdm/kgreet_generic.h b/kdm/kgreet_generic.h new file mode 100644 index 000000000..60c855f46 --- /dev/null +++ b/kdm/kgreet_generic.h @@ -0,0 +1,84 @@ +/* + +Conversation widget for kdm greeter + +Copyright (C) 2008 Dirk Mueller +Copyright (C) 2008 Oswald Buddenhagen + +based on classic kdm greeter: + + Copyright (C) 1997, 1998, 2000 Steffen Hansen + Copyright (C) 2000-2003 Oswald Buddenhagen + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +#ifndef KGREET_GENERIC_H +#define KGREET_GENERIC_H + +#include "kgreeterplugin.h" + +#include + +class QGridLayout; +class QWidget; +class KLineEdit; + +class KGenericGreeter : public QObject, public KGreeterPlugin { + Q_OBJECT + + public: + KGenericGreeter( KGreeterPluginHandler *handler, + QWidget *parent, const QString &fixedEntitiy, + Function func, Context ctx ); + ~KGenericGreeter(); + virtual void loadUsers( const QStringList &users ); + virtual void presetEntity( const QString &entity, int field ); + virtual QString getEntity() const; + virtual void setUser( const QString &user ); + virtual void setEnabled( bool on ); + virtual bool textMessage( const char *message, bool error ); + virtual void textPrompt( const char *prompt, bool echo, bool nonBlocking ); + virtual bool binaryPrompt( const char *prompt, bool nonBlocking ); + virtual void start(); + virtual void suspend(); + virtual void resume(); + virtual void next(); + virtual void abort(); + virtual void succeeded(); + virtual void failed(); + virtual void revive(); + virtual void clear(); + + public slots: + void slotLoginLostFocus(); + void slotChanged(); + + private: + QGridLayout *m_grid; + QList m_children; + KLineEdit *m_lineEdit; + QWidget *m_parentWidget; + QList m_infoMsgs; + QString fixedUser, curUser; + QStringList m_users; + Function func; + Context ctx; + int exp, m_line; + bool running, m_echo; +}; + +#endif /* KGREET_GENERIC_H */ diff --git a/kdm/kgreet_winbind.cpp b/kdm/kgreet_winbind.cpp new file mode 100644 index 000000000..f7cf4c88a --- /dev/null +++ b/kdm/kgreet_winbind.cpp @@ -0,0 +1,627 @@ +/* + +Conversation widget for kdm greeter + +Copyright (C) 1997, 1998, 2000 Steffen Hansen +Copyright (C) 2000-2004 Oswald Buddenhagen + + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +#include "kgreet_winbind.h" +#include "themer/kdmthemer.h" +#include "themer/kdmitem.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +static int echoMode; + +class KDMPasswordEdit : public KLineEdit { +public: + KDMPasswordEdit( QWidget *parent ) : KLineEdit( parent ) + { + if (::echoMode == -1) + setPasswordMode(true); + else + setEchoMode( ::echoMode ? Password : NoEcho ); + setContextMenuPolicy( Qt::NoContextMenu ); + } +}; + +static char separator; +static QStringList staticDomains; +static QString defaultDomain; + +static void +splitEntity( const QString &ent, QString &dom, QString &usr ) +{ + int pos = ent.indexOf( separator ); + if (pos < 0) + dom = "", usr = ent; + else + dom = ent.left( pos ), usr = ent.mid( pos + 1 ); +} + +KWinbindGreeter::KWinbindGreeter( KGreeterPluginHandler *_handler, + QWidget *parent, + const QString &_fixedEntity, + Function _func, Context _ctx ) : + QObject(), + KGreeterPlugin( _handler ), + func( _func ), + ctx( _ctx ), + exp( -1 ), + pExp( -1 ), + running( false ) +{ + QGridLayout *grid = 0; + + int line = 0; + + if (!_handler->gplugHasNode( "domain-entry" ) || + !_handler->gplugHasNode( "user-entry" ) || + !_handler->gplugHasNode( "pw-entry" )) + { + parent = new QWidget( parent ); + parent->setObjectName( "talker" ); + widgetList << parent; + grid = new QGridLayout( parent ); + grid->setMargin( 0 ); + } + + domainLabel = loginLabel = passwdLabel = passwd1Label = passwd2Label = 0; + domainCombo = 0; + loginEdit = 0; + passwdEdit = passwd1Edit = passwd2Edit = 0; + if (ctx == ExUnlock || ctx == ExChangeTok) + splitEntity( KUser().loginName(), fixedDomain, fixedUser ); + else + splitEntity( _fixedEntity, fixedDomain, fixedUser ); + if (func != ChAuthTok) { + if (fixedUser.isEmpty()) { + domainCombo = new KComboBox( parent ); + connect( domainCombo, SIGNAL(activated( const QString & )), + SLOT(slotChangedDomain( const QString & )) ); + connect( domainCombo, SIGNAL(activated( const QString & )), + SLOT(slotLoginLostFocus()) ); + connect( domainCombo, SIGNAL(activated( const QString & )), + SLOT(slotChanged()) ); + // should handle loss of focus + loginEdit = new KLineEdit( parent ); + loginEdit->setContextMenuPolicy( Qt::NoContextMenu ); + + if (!grid) { + loginEdit->setObjectName( "user-entry" ); + domainCombo->setObjectName( "domain-entry" ); + widgetList << domainCombo << loginEdit; + } else { + domainLabel = new QLabel( i18n("&Domain:"), parent ); + domainLabel->setBuddy( domainCombo ); + loginLabel = new QLabel( i18n("&Username:"), parent ); + loginLabel->setBuddy( loginEdit ); + grid->addWidget( domainLabel, line, 0 ); + grid->addWidget( domainCombo, line++, 1 ); + grid->addWidget( loginLabel, line, 0 ); + grid->addWidget( loginEdit, line++, 1 ); + } + connect( loginEdit, SIGNAL(editingFinished()), SLOT(slotLoginLostFocus()) ); + connect( loginEdit, SIGNAL(editingFinished()), SLOT(slotChanged()) ); + connect( loginEdit, SIGNAL(textChanged( const QString & )), SLOT(slotChanged()) ); + connect( loginEdit, SIGNAL(selectionChanged()), SLOT(slotChanged()) ); + domainCombo->addItems( staticDomains ); + QTimer::singleShot( 0, this, SLOT(slotStartDomainList()) ); + } else if (ctx != Login && ctx != Shutdown && grid) { + domainLabel = new QLabel( i18n("Domain:"), parent ); + grid->addWidget( domainLabel, line, 0 ); + grid->addWidget( new QLabel( fixedDomain, parent ), line++, 1 ); + loginLabel = new QLabel( i18n("Username:"), parent ); + grid->addWidget( loginLabel, line, 0 ); + grid->addWidget( new QLabel( fixedUser, parent ), line++, 1 ); + } + passwdEdit = new KDMPasswordEdit( parent ); + connect( passwdEdit, SIGNAL(textChanged( const QString & )), + SLOT(slotChanged()) ); + connect( passwdEdit, SIGNAL(editingFinished()), SLOT(slotChanged()) ); + + if (!grid) { + passwdEdit->setObjectName( "pw-entry" ); + widgetList << passwdEdit; + } else { + passwdLabel = new QLabel( func == Authenticate ? + i18n("&Password:") : + i18n("Current &password:"), + parent ); + passwdLabel->setBuddy( passwdEdit ); + grid->addWidget( passwdLabel, line, 0 ); + grid->addWidget( passwdEdit, line++, 1 ); + } + + if (loginEdit) + loginEdit->setFocus(); + else + passwdEdit->setFocus(); + } + if (func != Authenticate) { + passwd1Edit = new KDMPasswordEdit( parent ); + passwd1Label = new QLabel( i18n("&New password:"), parent ); + passwd1Label->setBuddy( passwd1Edit ); + passwd2Edit = new KDMPasswordEdit( parent ); + passwd2Label = new QLabel( i18n("Con&firm password:"), parent ); + passwd2Label->setBuddy( passwd2Edit ); + if (grid) { + grid->addWidget( passwd1Label, line, 0 ); + grid->addWidget( passwd1Edit, line++, 1 ); + grid->addWidget( passwd2Label, line, 0 ); + grid->addWidget( passwd2Edit, line, 1 ); + } + if (!passwdEdit) + passwd1Edit->setFocus(); + } +} + +// virtual +KWinbindGreeter::~KWinbindGreeter() +{ + abort(); + qDeleteAll( widgetList ); +} + +void +KWinbindGreeter::slotChangedDomain( const QString &dom ) +{ + if (!loginEdit->completionObject()) + return; + QStringList users; + if (dom == "") { + for (QStringList::ConstIterator it = allUsers.begin(); it != allUsers.end(); ++it) + if ((*it).indexOf( separator ) < 0) + users << *it; + } else { + QString st( dom + separator ); + for (QStringList::ConstIterator it = allUsers.begin(); it != allUsers.end(); ++it) + if ((*it).startsWith( st )) + users << (*it).mid( st.length() ); + } + loginEdit->completionObject()->setItems( users ); +} + +void // virtual +KWinbindGreeter::loadUsers( const QStringList &users ) +{ + allUsers = users; + KCompletion *userNamesCompletion = new KCompletion; + loginEdit->setCompletionObject( userNamesCompletion ); + loginEdit->setAutoDeleteCompletionObject( true ); + loginEdit->setCompletionMode( KGlobalSettings::CompletionAuto ); + slotChangedDomain( defaultDomain ); +} + +void // virtual +KWinbindGreeter::presetEntity( const QString &entity, int field ) +{ + QString dom, usr; + splitEntity( entity, dom, usr ); + domainCombo->setCurrentItem( dom, true ); + slotChangedDomain( dom ); + loginEdit->setText( usr ); + if (field > 1) + passwdEdit->setFocus(); + else if (field == 1 || field == -1) { + if (field == -1) { + passwdEdit->setText( " " ); + passwdEdit->setEnabled( false ); + authTok = false; + } + loginEdit->setFocus(); + loginEdit->selectAll(); + } + curUser = entity; +} + +QString // virtual +KWinbindGreeter::getEntity() const +{ + QString dom, usr; + if (fixedUser.isEmpty()) + dom = domainCombo->currentText(), usr = loginEdit->text(); + else + dom = fixedDomain, usr = fixedUser; + return dom == "" ? usr : dom + separator + usr; +} + +void // virtual +KWinbindGreeter::setUser( const QString &user ) +{ + // assert (fixedUser.isEmpty()); + curUser = user; + QString dom, usr; + splitEntity( user, dom, usr ); + domainCombo->setCurrentItem( dom, true ); + slotChangedDomain( dom ); + loginEdit->setText( usr ); + passwdEdit->setFocus(); + passwdEdit->selectAll(); +} + +void // virtual +KWinbindGreeter::setEnabled( bool enable ) +{ + // assert( !passwd1Label ); + // assert( func == Authenticate && ctx == Shutdown ); +// if (domainCombo) +// domainCombo->setEnabled( enable ); +// if (loginLabel) +// loginLabel->setEnabled( enable ); + passwdLabel->setEnabled( enable ); + setActive( enable ); + if (enable) + passwdEdit->setFocus(); +} + +void // private +KWinbindGreeter::returnData() +{ + switch (exp) { + case 0: + handler->gplugReturnText( getEntity().toLocal8Bit(), + KGreeterPluginHandler::IsUser ); + break; + case 1: + handler->gplugReturnText( passwdEdit->text().toLocal8Bit(), + KGreeterPluginHandler::IsPassword | + KGreeterPluginHandler::IsSecret ); + break; + case 2: + handler->gplugReturnText( passwd1Edit->text().toLocal8Bit(), + KGreeterPluginHandler::IsSecret ); + break; + default: // case 3: + handler->gplugReturnText( passwd2Edit->text().toLocal8Bit(), + KGreeterPluginHandler::IsNewPassword | + KGreeterPluginHandler::IsSecret ); + break; + } +} + +bool // virtual +KWinbindGreeter::textMessage( const char *text, bool err ) +{ + if (!err && + QString( text ).indexOf( QRegExp( "^Changing password for [^ ]+$" ) ) >= 0) + return true; + return false; +} + +void // virtual +KWinbindGreeter::textPrompt( const char *prompt, bool echo, bool nonBlocking ) +{ + pExp = exp; + if (echo) + exp = 0; + else if (!authTok) + exp = 1; + else { + QString pr( prompt ); + if (pr.indexOf( QRegExp( "\\b(old|current)\\b", Qt::CaseInsensitive ) ) >= 0) { + handler->gplugReturnText( "", + KGreeterPluginHandler::IsOldPassword | + KGreeterPluginHandler::IsSecret ); + return; + } else if (pr.indexOf( QRegExp( "\\b(re-?(enter|type)|again|confirm|repeat)\\b", + Qt::CaseInsensitive ) ) >= 0) + exp = 3; + else if (pr.indexOf( QRegExp( "\\bnew\\b", Qt::CaseInsensitive ) ) >= 0) + exp = 2; + else { + handler->gplugMsgBox( QMessageBox::Critical, + i18n("Unrecognized prompt \"%1\"", + prompt ) ); + handler->gplugReturnText( 0, 0 ); + exp = -1; + return; + } + } + + if (pExp >= 0 && pExp >= exp) { + revive(); + has = -1; + } + + if (has >= exp || nonBlocking) + returnData(); +} + +bool // virtual +KWinbindGreeter::binaryPrompt( const char *, bool ) +{ + // this simply cannot happen ... :} + return true; +} + +void // virtual +KWinbindGreeter::start() +{ + authTok = !(passwdEdit && passwdEdit->isEnabled()); + exp = has = -1; + running = true; +} + +void // virtual +KWinbindGreeter::suspend() +{ +} + +void // virtual +KWinbindGreeter::resume() +{ +} + +void // virtual +KWinbindGreeter::next() +{ + // assert( running ); + if (domainCombo && domainCombo->hasFocus()) + loginEdit->setFocus(); + else if (loginEdit && loginEdit->hasFocus()) { + passwdEdit->setFocus(); // will cancel running login if necessary + has = 0; + } else if (passwdEdit && passwdEdit->hasFocus()) { + if (passwd1Edit) + passwd1Edit->setFocus(); + has = 1; + } else if (passwd1Edit) { + if (passwd1Edit->hasFocus()) { + passwd2Edit->setFocus(); + has = 1; // sic! + } else + has = 3; + } else + has = 1; + if (exp < 0) + handler->gplugStart(); + else if (has >= exp) + returnData(); +} + +void // virtual +KWinbindGreeter::abort() +{ + running = false; + if (exp >= 0) { + exp = -1; + handler->gplugReturnText( 0, 0 ); + } +} + +void // virtual +KWinbindGreeter::succeeded() +{ + // assert( running || timed_login ); + if (!authTok) { + setActive( false ); + if (passwd1Edit) { + authTok = true; + return; + } + } else + setActive2( false ); + exp = -1; + running = false; +} + +void // virtual +KWinbindGreeter::failed() +{ + // assert( running || timed_login ); + setActive( false ); + setActive2( false ); + exp = -1; + running = false; +} + +void // virtual +KWinbindGreeter::revive() +{ + // assert( !running ); + setActive2( true ); + if (authTok) { + passwd1Edit->clear(); + passwd2Edit->clear(); + passwd1Edit->setFocus(); + } else { + passwdEdit->clear(); + if (loginEdit && loginEdit->isEnabled()) + passwdEdit->setEnabled( true ); + else { + setActive( true ); + if (loginEdit && loginEdit->text().isEmpty()) + loginEdit->setFocus(); + else + passwdEdit->setFocus(); + } + } +} + +void // virtual +KWinbindGreeter::clear() +{ + // assert( !running && !passwd1Edit ); + passwdEdit->clear(); + if (loginEdit) { + domainCombo->setCurrentItem( defaultDomain ); + slotChangedDomain( defaultDomain ); + loginEdit->clear(); + loginEdit->setFocus(); + curUser.clear(); + } else + passwdEdit->setFocus(); +} + + +// private + +void +KWinbindGreeter::setActive( bool enable ) +{ + if (domainCombo) + domainCombo->setEnabled( enable ); + if (loginEdit) + loginEdit->setEnabled( enable ); + if (passwdEdit) + passwdEdit->setEnabled( enable ); +} + +void +KWinbindGreeter::setActive2( bool enable ) +{ + if (passwd1Edit) { + passwd1Edit->setEnabled( enable ); + passwd2Edit->setEnabled( enable ); + } +} + +void +KWinbindGreeter::slotLoginLostFocus() +{ + if (!running) + return; + QString ent( getEntity() ); + if (exp > 0) { + if (curUser == ent) + return; + exp = -1; + handler->gplugReturnText( 0, 0 ); + } + curUser = ent; + handler->gplugSetUser( curUser ); +} + +void +KWinbindGreeter::slotChanged() +{ + if (running) + handler->gplugChanged(); +} + +void +KWinbindGreeter::slotStartDomainList() +{ + m_domainLister = new KProcess( this ); + (*m_domainLister) << "wbinfo" << "--own-domain" << "--trusted-domains"; + m_domainLister->setOutputChannelMode( KProcess::OnlyStdoutChannel ); + connect( m_domainLister, SIGNAL(finished( int, QProcess::ExitStatus )), + SLOT(slotEndDomainList()) ); + m_domainLister->start(); +} + +void +KWinbindGreeter::slotEndDomainList() +{ + QStringList domainList; + + while (!m_domainLister->atEnd()) { + QString dom = m_domainLister->readLine(); + dom.chop( 1 ); + if (!staticDomains.contains( dom )) + domainList.append( dom ); + } + + delete m_domainLister; + + for (int i = domainCombo->count(), min = staticDomains.count(); --i >= min; ) { + int dli = domainList.indexOf( domainCombo->itemText( i ) ); + if (dli < 0) { + if (i == domainCombo->currentIndex()) + domainCombo->setCurrentItem( defaultDomain ); + domainCombo->removeItem( i ); + } else + domainList.removeAt( dli ); + } + domainCombo->addItems( domainList ); + + QTimer::singleShot( 5 * 1000, this, SLOT(slotStartDomainList()) ); +} + +// factory + +static bool init( const QString &, + QVariant (*getConf)( void *, const char *, const QVariant & ), + void *ctx ) +{ + echoMode = getConf( ctx, "EchoPasswd", QVariant( -1 ) ).toInt(); + + staticDomains = getConf( ctx, "winbind.Domains", QVariant( "" ) ).toString().split( ':', QString::SkipEmptyParts ); + if (!staticDomains.size()) + staticDomains << ""; + defaultDomain = getConf( ctx, "winbind.DefaultDomain", QVariant( staticDomains.first() ) ).toString(); + QString sepstr = getConf( ctx, "winbind.Separator", QVariant( QString() ) ).toString(); + if (sepstr.isNull()) { + FILE *sepfile = popen( "wbinfo --separator 2>/dev/null", "r" ); + if (sepfile) { + QTextStream( sepfile ) >> sepstr; + if (pclose( sepfile )) + sepstr = "\\"; + } else + sepstr = "\\"; + } + separator = sepstr[0].toLatin1(); + + KGlobal::locale()->insertCatalog( "kgreet_winbind" ); + return true; +} + +static void done( void ) +{ + KGlobal::locale()->removeCatalog( "kgreet_winbind" ); + // avoid static deletion problems ... hopefully + staticDomains.clear(); + defaultDomain.clear(); +} + +static KGreeterPlugin * +create( KGreeterPluginHandler *handler, + QWidget *parent, + const QString &fixedEntity, + KGreeterPlugin::Function func, + KGreeterPlugin::Context ctx ) +{ + return new KWinbindGreeter( handler, parent, fixedEntity, func, ctx ); +} + +KDE_EXPORT KGreeterPluginInfo kgreeterplugin_info = { + I18N_NOOP2("@item:inmenu authentication method", "Winbind / Samba"), "classic", + KGreeterPluginInfo::Local | KGreeterPluginInfo::Fielded | KGreeterPluginInfo::Presettable, + init, done, create +}; + +#include "kgreet_winbind.moc" diff --git a/kdm/kgreet_winbind.h b/kdm/kgreet_winbind.h new file mode 100644 index 000000000..f317fd83e --- /dev/null +++ b/kdm/kgreet_winbind.h @@ -0,0 +1,94 @@ +/* + +Conversation widget for kdm greeter + +Copyright (C) 1997, 1998 Steffen Hansen +Copyright (C) 2000-2003 Oswald Buddenhagen + + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + + +#ifndef KGREET_WINBIND_H +#define KGREET_WINBIND_H + +#include "kgreeterplugin.h" + +#include +#include + +class KComboBox; +class KLineEdit; +class KSimpleConfig; +class QLabel; +class KProcess; + +class KWinbindGreeter : public QObject, public KGreeterPlugin { + Q_OBJECT + + public: + KWinbindGreeter( KGreeterPluginHandler *handler, + QWidget *parent, + const QString &fixedEntitiy, + Function func, Context ctx ); + ~KWinbindGreeter(); + virtual void loadUsers( const QStringList &users ); + virtual void presetEntity( const QString &entity, int field ); + virtual QString getEntity() const; + virtual void setUser( const QString &user ); + virtual void setEnabled( bool on ); + virtual bool textMessage( const char *message, bool error ); + virtual void textPrompt( const char *prompt, bool echo, bool nonBlocking ); + virtual bool binaryPrompt( const char *prompt, bool nonBlocking ); + virtual void start(); + virtual void suspend(); + virtual void resume(); + virtual void next(); + virtual void abort(); + virtual void succeeded(); + virtual void failed(); + virtual void revive(); + virtual void clear(); + + public Q_SLOTS: + void slotLoginLostFocus(); + void slotChangedDomain( const QString &dom ); + void slotChanged(); + void slotStartDomainList(); + void slotEndDomainList(); + + private: + void setActive( bool enable ); + void setActive2( bool enable ); + void returnData(); + + QLabel *domainLabel, *loginLabel, *passwdLabel, *passwd1Label, *passwd2Label; + KComboBox *domainCombo; + KLineEdit *loginEdit; + KLineEdit *passwdEdit, *passwd1Edit, *passwd2Edit; + KSimpleConfig *stsFile; + QString fixedDomain, fixedUser, curUser; + QStringList allUsers; + KProcess* m_domainLister; + + Function func; + Context ctx; + int exp, pExp, has; + bool running, authTok; +}; + +#endif /* KGREET_WINBIND_H */ diff --git a/kdm/kgreeterplugin.h b/kdm/kgreeterplugin.h new file mode 100644 index 000000000..9aada349d --- /dev/null +++ b/kdm/kgreeterplugin.h @@ -0,0 +1,410 @@ +/* + + Authentication method specific conversation plugin for KDE's greeter widgets + + Copyright (C) 2003 Oswald Buddenhagen + Copyright (C) 2003 Fabian Kaiser + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This 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 KGREETERPLUGIN_H +#define KGREETERPLUGIN_H + +#include +#include +#include + +class QWidget; + +class KGreeterPluginHandler { +public: + virtual ~KGreeterPluginHandler() {} + /* keep in sync with V_IS_* */ + enum { IsSecret = 1, IsUser = 2, IsPassword = 4, IsOldPassword = 8, + IsNewPassword = 16 }; + /** + * Reply to textPrompt(). + * @param text text to return to core; null to abort auth cycle + * @param tag zero or one of Is* + */ + virtual void gplugReturnText( const char *text, int tag ) = 0; + /** + * Reply to binaryPrompt(). + * @param data data in pam_client format to return to the core; + * null to abort auth cycle + */ + virtual void gplugReturnBinary( const char *data ) = 0; + /** + * Tell the greeter who is logging in. + * Call this preferably before gplugStart, as otherwise the .dmrc + * load will be delayed. Don't call at all if your plugin doesn't + * have the Local flag set. Call only for internally generated + * user changes. + * @param user the user logging in + */ + virtual void gplugSetUser( const QString &user ) = 0; + /** + * Start processing. + */ + virtual void gplugStart() = 0; + /** + * This should be called each time the talker changes in any way from the + * pristine state after an authentication cycle starts, so the greeter + * knows it must reset the fields after some time of inactivity. + */ + virtual void gplugChanged() = 0; + /** + * Plugins that expect user input from a different device than the mouse or + * keyboard must call this when user activity is detected to prevent the + * greeter from resetting/going away. Events should be compressed to no + * more than ten per second; one every five seconds is actually enough. + * Events should be actual changes to the input fields, not random motion. + */ + virtual void gplugActivity() = 0; + /** + * Show a message box on behalf of the talker. + * @param type message severity + * @param text message text + */ + virtual void gplugMsgBox( QMessageBox::Icon type, const QString &text ) = 0; + /** + * Determine if the named widget is welcomed. + * @param id the widget name + */ + virtual bool gplugHasNode( const QString &id ) = 0; +}; + +/** + * Abstract base class for conversation plugins ("talkers") to be used with + * KDM, kdesktop_lock, etc. + * The authentication method used by a particular instance of a plugin + * may be configurable, but the instance must handle exactly one method, + * i.e., info->method must be determined at the latest at init() time. + */ +class KGreeterPlugin { +public: + KGreeterPlugin( KGreeterPluginHandler *h ) : handler( h ) {} + virtual ~KGreeterPlugin() {} + + /** + * Variations of the talker: + * - Authenticate: authentication + * - AuthChAuthTok: authentication and password change + * - ChAuthTok: password change + */ + enum Function { Authenticate, AuthChAuthTok, ChAuthTok }; + + /** + * Contexts the talker can be used in: + * - Login: kdm login dialog + * - Shutdown: kdm shutdown dialog + * - Unlock: kdm unlock dialog (TODO) + * - ChangeTok: kdm password change dialog (TODO) + * - ExUnlock: kdesktop_lock unlock dialog + * - ExChangeTok: kdepasswd password change dialog (TODO) + * + * The Ex* contexts exist within a running session; the talker must know + * how to obtain the currently logged in user (+ domain/realm, etc.) + * itself (i.e., fixedEntity will be null). The non-Ex variants will have + * a fixedEntity passed in. + */ + enum Context { Login, Shutdown, Unlock, ChangeTok, + ExUnlock, ExChangeTok }; + + /** + * Provide the talker with a list of selectable users. This can be used + * for autocompletion, etc. + * Will be called only when not running. + * @param users the users to load. + */ + virtual void loadUsers( const QStringList &users ) = 0; + + /** + * Preload the talker with an (opaque to the greeter) entity. + * Will be called only when not running. + * @param entity the entity to preload the talker with. That + * will usually be something like "user" or "user@domain". + * @param field the sub-widget (probably line edit) to put the cursor into. + * If -1, preselect the user for timed login. This means pre-filling + * the password field with anything, disabling it, and placing the + * cursor in the user name field. + */ + virtual void presetEntity( const QString &entity, int field ) = 0; + + /** + * Obtain the actually logged in entity. + * Will be called only after succeeded() was called. + */ + virtual QString getEntity() const = 0; + + /** + * "Push" a user into the talker. That can be a click into the user list + * or successful authentication without the talker calling gplugSetUser. + * Will be called only when running. + * @param user the user to set. Note that this is a UNIX login, not a + * canonical entity + */ + virtual void setUser( const QString &user ) = 0; + + /** + * En-/disable any widgets contained in the talker. + * Will be called only when not running. + * @param on the state to set + */ + virtual void setEnabled( bool on ) = 0; + + /** + * Called when a message from the authentication backend arrives. + * @param message the message received from the backend + * @param error if true, @p message is an error message, otherwise it's + * an informational message + * @return true means that the talker already handled the message, false + * that the greeter should display it in a message box + * + * FIXME: Filtering a message usually means that the backend issued a + * prompt and obtains the authentication data itself. However, in that + * state the backend is unresponsive, e.g., no shutdown is possible. + * The frontend could send the backend a signal, but the "escape path" + * within the backend is unclear (PAM won't like simply longjmp()ing + * out of it). + */ + virtual bool textMessage( const char *message, bool error ) = 0; + + /** + * Prompt the user for data. Reply by calling handler->gplugReturnText(). + * @param propmt the prompt to display. It may be null, in which case + * "Username"/"Password" should be shown and the replies should be tagged + * with the respective Is* flag. + * @param echo if true, a normal input widget can be used, otherwise one that + * visually obscures the user's input. + * @param nonBlocking if true, report whatever is already available, + * otherwise wait for user input. + */ + virtual void textPrompt( const char *prompt, bool echo, bool nonBlocking ) = 0; + + /** + * Request binary authentication data from the talker. Reply by calling + * handler->gplugReturnBinary(). + * @param prompt prompt in pam_client format + * @param nonBlocking if true, report whatever is already available, + * otherwise wait for user input. + * @return always true for now + * + * TODO: + * @return if true, the prompt was handled by the talker, otherwise the + * handler has to use libpam_client to obtain the authentication data. + * In that state the talker still can abort the data fetch by + * gplugReturn()ing a null array. When the data was obtained, another + * binaryPrompt with a null prompt will be issued. + */ + virtual bool binaryPrompt( const char *prompt, bool nonBlocking ) = 0; + + /** + * This can either + * - Start a processing cycle. Will be called only when not running. + * - Restart authTok cycle - will be called while running and implies + * revive(). PAM is a bit too clever, so we need this. + * In any case the talker is running afterwards. + */ + virtual void start() = 0; + + /** + * Request to suspend the auth. Make sure that a second talker of any + * type will be able to operate while this one is suspended (no busy + * device nodes, etc.). + * Will be called only if running within Login context. (Actually it + * won't be called at all, but be prepared.) + */ + virtual void suspend() = 0; + + /** + * Request to resume the auth from the point it was suspended at. + * Will be called only when suspended. + */ + virtual void resume() = 0; + + /** + * The "login" button was pressed in the greeter. + * This might call gplugReturn* or gplugStart. + * Will be called only when running. + */ + virtual void next() = 0; + + /** + * Abort auth cycle. Note that this should _not_ clear out already + * entered auth tokens if they are still on the screen. + * Will be called only when running and stops it. + */ + virtual void abort() = 0; + + /** + * Indicate successful end of the current phase. + * This is more or less a request to disable editable widgets + * responsible for the that phase. + * There will be no further attempt to enter that phase until the + * widget is destroyed. + * Will be called only when running and stops it. + */ + virtual void succeeded() = 0; + + /** + * Indicate unsuccessful end of the current phase. + * This is mostly a request to disable all editable widgets. + * The widget will be treated as dead until revive() is called. + * Will be called only when running and stops it. + */ + virtual void failed() = 0; + + /** + * Prepare retrying the previously failed phase. + * This is mostly a request to re-enable all editable widgets failed() + * disabled previously, clear the probably incorrect authentication tokens + * and to set the input focus appropriately. + * Will be called only after failed() (possibly with clear() in between), + * or after presetEntity() with field -1. + */ + virtual void revive() = 0; + + /** + * Clear any edit widgets, particularly anything set by setUser. + * Will be called only when not running. + */ + virtual void clear() = 0; + + typedef QList WidgetList; + + /** + * Obtain the QWidget to actually handle the conversation. + */ + const WidgetList &getWidgets() const { return widgetList; } + +protected: + KGreeterPluginHandler *handler; + WidgetList widgetList; +}; + +struct KDE_EXPORT KGreeterPluginInfo { + /** + * Human readable name of this plugin (should be a little more + * informative than just the libary name). Must be I18N_NOOP()ed. + */ + const char *name; + + /** + * The authentication method to use - the meaning is up to the backend, + * but will usually be related to the PAM service. + */ + const char *method; + + /** + * Capabilities. + */ + enum { + /** + * All users exist on the local system permanently (will be listed + * by getpwent()); an entity corresponds to a UNIX user. + */ + Local = 1, + /** + * The entities consist of multiple fields. + * PluginOptions/.FocusField is used instead of FocusPasswd. + */ + Fielded = 2, + /** + * An entity can be preset, the talker has a widget where a user can + * be selected explicitly. If the method is "classic", timed login + * is possible, too. + * This also means that setUser/gplugSetUser can be used and a + * userlist can be shown at all - provided Local is set as well. + */ + Presettable = 4 + }; + + /* + * Capability flags. + */ + int flags; + + /** + * Call after loading the plugin. + * + * @param method if non-empty and the plugin is unable to handle that + * method, return false. If the plugin has a constant method defined + * above, it can ignore this parameter. + * @param getConf can be used to obtain configuration items from the + * greeter; you have to pass it the @p ctx pointer. + * The only predefined key (in KDM) is "EchoMode", which is an int + * (in fact, QLineEdit::EchoModes). + * Other keys are obtained from the PluginOptions option; see kdmrc + * for details. + * If the key is unknown, dflt is returned. + * @param ctx context pointer for @p getConf + * @return if false, unload the plugin again (don't call done() first) + */ + bool (*init)( const QString &method, + QVariant (*getConf)( void *ctx, const char *key, + const QVariant &dflt ), + void *ctx ); + + /** + * Call before unloading the plugin. + * This pointer can be null. + */ + void (*done)( void ); + + /** + * Factory method to create an instance of the plugin. + * Note that multiple instances can exist at one time, but only + * one of them is active at any moment (the others would be suspended + * or not running at all). + * @param handler the object offering the necessary callbacks + * @param parent parent widget + * @param predecessor the focus widget before the conversation widget + * @param fixedEntity see below + * @param func see below + * @param ctx see below + * @return an instance of this conversation plugin + * + * Valid combinations of Function and Context: + * - Authenticate:Login - init + * - Authenticate:Shutdown - init, for now "root" is passed as fixedEntitiy + * and it is not supposed to be displayed. Plugins with Local not set + * might have to conjure something up to make getEntity() return a + * canonical entitiy. FIXME: don't restrict shutdown to root. + * - AuthChAuthTok:Login, AuthChAuthTok:Shutdown - cont/cont, + * only relevant for classic method (as it is relevant only for password- + * less logins, which always use classic). The login should not be shown - + * it is known to the user already; the backend won't ask for it, either. + * - ChAuthTok:Login & ChAuthTok:Shutdown - cont + * - Authenticate:Unlock & Authenticate:ExUnlock - init, + * AuthChAuthTok:ChangeTok & AuthChAuthTok:ExChangeTok - init/cont, + * display fixedEntity as labels. The backend does not ask for the UNIX + * login, as it already knows it - but it will ask for all components of + * the entity if it is no UNIX login. + * + * "init" means that the plugin is supposed to call gplugStart, "cont" + * that the backend is already in a cycle of the method the plugin was + * initialized with (it does not hurt if gplugStart is still called). + */ + KGreeterPlugin *(*create)( KGreeterPluginHandler *handler, + QWidget *parent, + const QString &fixedEntity, + KGreeterPlugin::Function func, + KGreeterPlugin::Context ctx ); +}; + +#endif diff --git a/ksysguard/CMakeLists.txt b/ksysguard/CMakeLists.txt new file mode 100644 index 000000000..26298b550 --- /dev/null +++ b/ksysguard/CMakeLists.txt @@ -0,0 +1,13 @@ + +########### next target ############### + +add_subdirectory( lsofui ) +add_subdirectory( processcore ) +add_subdirectory( processui ) +add_subdirectory( tests ) + +check_include_files(sys/ptrace.h HAVE_SYS_PTRACE_H) + +configure_file(config-ksysguard.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-ksysguard.h ) + + diff --git a/ksysguard/config-ksysguard.h.cmake b/ksysguard/config-ksysguard.h.cmake new file mode 100644 index 000000000..b495cb390 --- /dev/null +++ b/ksysguard/config-ksysguard.h.cmake @@ -0,0 +1,8 @@ +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_PTRACE_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_ENDIAN_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_BYTESWAP_H 1 diff --git a/ksysguard/lsofui/CMakeLists.txt b/ksysguard/lsofui/CMakeLists.txt new file mode 100644 index 000000000..43c13478d --- /dev/null +++ b/ksysguard/lsofui/CMakeLists.txt @@ -0,0 +1,33 @@ + +########### next target ############### + +set(lsofui_LIB_SRCS + lsof.cpp +) + +kde4_add_ui_files( lsofui_LIB_SRCS + LsofSearchWidget.ui +) + +kde4_add_library(lsofui SHARED ${lsofui_LIB_SRCS}) + +target_link_libraries(lsofui ${KDE4_KIO_LIBS} ) +set_target_properties(lsofui PROPERTIES VERSION ${GENERIC_LIB_VERSION} SOVERSION ${GENERIC_LIB_SOVERSION} ) +install(TARGETS lsofui ${INSTALL_TARGETS_DEFAULT_ARGS} ) + +########### install files ############### + +install( FILES lsof.h DESTINATION ${INCLUDE_INSTALL_DIR}/ksysguard) + +set(ksysguardlsofwidgets_PART_SRCS + ${CMAKE_CURRENT_BINARY_DIR}/ksysguardlsofwidgets.cpp +) + +KDE4_ADD_WIDGET_FILES(${ksysguardlsofwidgets_PART_SRCS} ksysguardlsof.widgets) + +kde4_add_plugin(ksysguardlsofwidgets ${ksysguardlsofwidgets_PART_SRCS}) + +target_link_libraries(ksysguardlsofwidgets ${KDE4_KDECORE_LIBS} ${QT_QTGUI_LIBRARY} lsofui) + +install(TARGETS ksysguardlsofwidgets DESTINATION ${PLUGIN_INSTALL_DIR}/plugins/designer ) + diff --git a/ksysguard/lsofui/LsofSearchWidget.cpp b/ksysguard/lsofui/LsofSearchWidget.cpp new file mode 100644 index 000000000..45b45811d --- /dev/null +++ b/ksysguard/lsofui/LsofSearchWidget.cpp @@ -0,0 +1,46 @@ +/* + KSysGuard, the KDE System Guard + + Copyright (c) 1999 Chris Schlaeger + Copyright (c) 2007 John Tapsell + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This 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 +#include + +#include "LsofSearchWidget.moc" +#include "ui_LsofSearchWidget.h" + +LsofSearchWidget::LsofSearchWidget(QWidget* parent, int pid ) + : KDialog( parent ) +{ + setObjectName( "Renice Dialog" ); + setModal( true ); + setCaption( i18n("Renice Process") ); + setButtons( Close ); + showButtonSeparator( false ); + QWidget *widget = new QWidget(this); + setMainWidget(widget); + ui = new Ui_LsofSearchWidget(); + ui->setupUi(widget); + ui->klsofwidget->setPid(pid); + ktreewidgetsearchline +} + diff --git a/ksysguard/lsofui/LsofSearchWidget.h b/ksysguard/lsofui/LsofSearchWidget.h new file mode 100644 index 000000000..ee0f89554 --- /dev/null +++ b/ksysguard/lsofui/LsofSearchWidget.h @@ -0,0 +1,45 @@ +/* + KSysGuard, the KDE System Guard + + Copyright (c) 2008 John Tapsell + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This 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 _LsofSearchWidget_h_ +#define _LsofSearchWidget_h_ + +#include + +class Ui_LsofSearchWidget; + +/** + * This class creates and handles a simple dialog to change the scheduling + * priority of a process. + */ +class LsofSearchWidget : public KDialog +{ + Q_OBJECT + +public: + LsofSearchWidget(QWidget *parent); + +private: + Ui_LsofSearchWidget *ui; +}; + +#endif diff --git a/ksysguard/lsofui/LsofSearchWidget.ui b/ksysguard/lsofui/LsofSearchWidget.ui new file mode 100644 index 000000000..bb4f88a31 --- /dev/null +++ b/ksysguard/lsofui/LsofSearchWidget.ui @@ -0,0 +1,54 @@ + + KLsofSearchWidget + + + + 0 + 0 + 956 + 686 + + + + + + + + + + false + + + + Stream + + + + + Type + + + + + Filename + + + + + + + + + KTreeWidgetSearchLine + KLineEdit +
ktreewidgetsearchline.h
+
+ + KLsofWidget + QTreeWidget +
lsof.h
+
+
+ + +
diff --git a/ksysguard/lsofui/Messages.sh b/ksysguard/lsofui/Messages.sh new file mode 100755 index 000000000..915195e70 --- /dev/null +++ b/ksysguard/lsofui/Messages.sh @@ -0,0 +1,2 @@ +#! /usr/bin/env bash +$XGETTEXT *.cpp -o $podir/ksysguardlsofwidgets.pot diff --git a/ksysguard/lsofui/ksysguardlsof.widgets b/ksysguard/lsofui/ksysguardlsof.widgets new file mode 100644 index 000000000..5673bee5b --- /dev/null +++ b/ksysguard/lsofui/ksysguardlsof.widgets @@ -0,0 +1,8 @@ +[Global] +PluginName=KSysGuardLsofWidgets + +[KLsofWidget] +Group=KSysGuard (KDE) +ConstructorArgs=(parent) +IncludeFile=lsof.h + diff --git a/ksysguard/lsofui/lsof.cpp b/ksysguard/lsofui/lsof.cpp new file mode 100644 index 000000000..755504f74 --- /dev/null +++ b/ksysguard/lsofui/lsof.cpp @@ -0,0 +1,86 @@ +#include +#include +#include + +#include "lsof.h" + +struct KLsofWidgetPrivate { + qlonglong pid; + QProcess *process; +}; + +KLsofWidget::KLsofWidget(QWidget *parent) : QTreeWidget(parent), d(new KLsofWidgetPrivate) +{ + d->pid = -1; + setColumnCount(3); + setUniformRowHeights(true); + setRootIsDecorated(false); + setItemsExpandable(false); + setSortingEnabled(true); + setAllColumnsShowFocus(true); + setHeaderLabels(QStringList() << i18nc("Short for File Descriptor", "FD") << i18n("Type") << i18n("Object")); + d->process = new QProcess(this); + connect(d->process, SIGNAL(finished ( int, QProcess::ExitStatus)), this, SLOT(finished(int, QProcess::ExitStatus))); +} + +KLsofWidget::~KLsofWidget() +{ + delete d; +} + +qlonglong KLsofWidget::pid() const +{ + return d->pid; +} + +void KLsofWidget::setPid(qlonglong pid) { + d->pid = pid; + update(); +} + +bool KLsofWidget::update() +{ + clear(); + QStringList args; + d->process->waitForFinished(); + args << "-Fftn"; + if(d->pid > 0) + args << ("-p" + QString::number(d->pid)); + d->process->start("lsof", args); + return true; +} + +void KLsofWidget::finished ( int exitCode, QProcess::ExitStatus exitStatus ) +{ + char buf[1024]; + QTreeWidgetItem *process = NULL; + while(true) { + qint64 lineLength = d->process->readLine(buf, sizeof(buf)); + + if(lineLength <= 0) + break; + if(buf[lineLength-1] == '\n') + lineLength--; + + switch(buf[0]) { + /* Process related stuff */ + case 'f': + process = new QTreeWidgetItem(this); + process->setText(0,QString::fromUtf8(buf+1, lineLength - 1)); + break; + case 't': + if(process) + process->setText(1,QString::fromUtf8(buf+1, lineLength - 1)); + break; + + case 'n': + if(process) + process->setText(2,QString::fromUtf8(buf+1, lineLength - 1)); + break; + default: + break; + } + } +} + +#include "lsof.moc" diff --git a/ksysguard/lsofui/lsof.h b/ksysguard/lsofui/lsof.h new file mode 100644 index 000000000..1b7bb3aaf --- /dev/null +++ b/ksysguard/lsofui/lsof.h @@ -0,0 +1,83 @@ +/* This file is part of the KDE project + + Copyright (C) 2007 John Tapsell + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This 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 LSOFWIDGET_H_ +#define LSOFWIDGET_H_ + +#include +#include +#include +#include + +struct KLsofWidgetPrivate; + +class KDE_EXPORT KLsofWidget : public QTreeWidget { + Q_OBJECT + Q_PROPERTY( qlonglong pid READ pid WRITE setPid ) + public: + KLsofWidget(QWidget *parent = NULL); + ~KLsofWidget(); + bool update(); + + private Q_SLOTS: + /* For QProcess *process */ + //void error ( QProcess::ProcessError error ); + void finished ( int exitCode, QProcess::ExitStatus exitStatus ); + //void readyReadStandardError (); + //void readyReadStandardOutput (); + //void started (); + qlonglong pid() const; + void setPid(qlonglong pid); + private: + KLsofWidgetPrivate* const d; +}; + +/* class LsofProcessInfo { + public: + pid_t tpid; + int pidst; + pid_t pid; + pid_t ppid; + pid_t pgrp; + int uid; + QString cmd; + QString login; + }; + class LsofFileInfo { + QString file_descriptor; + char access; + int file_struct_share_count; + char device_character_code; + long major_minor; + long file_struct_address; + long file_flags; + long inode; + long link_count; + char lock; + long file_struct_node_id; + long file_offset; + QString protocol_name; + QString stream_module; + QString file_type; + QString tcp_info; + }; +*/ +#endif diff --git a/ksysguard/processcore/CMakeLists.txt b/ksysguard/processcore/CMakeLists.txt new file mode 100644 index 000000000..d6946074c --- /dev/null +++ b/ksysguard/processcore/CMakeLists.txt @@ -0,0 +1,28 @@ + +########### next target ############### + +set(ksysguard_LIB_SRCS + processes.cpp + process.cpp + processes_local_p.cpp + processes_remote_p.cpp + processes_base_p.cpp +) + + + +kde4_add_library(processcore SHARED ${ksysguard_LIB_SRCS}) + +target_link_libraries(processcore ${KDE4_KDECORE_LIBS} ) +if( ${CMAKE_SYSTEM_NAME} MATCHES "NetBSD" ) + message(STATUS "Adding kvm library on NetBSD") + target_link_libraries(processcore kvm) +endif( ${CMAKE_SYSTEM_NAME} MATCHES "NetBSD" ) + +set_target_properties(processcore PROPERTIES VERSION ${GENERIC_LIB_VERSION} SOVERSION ${GENERIC_LIB_SOVERSION} ) +install(TARGETS processcore ${INSTALL_TARGETS_DEFAULT_ARGS} ) + +########### install files ############### + +install( FILES processes.h process.h DESTINATION ${INCLUDE_INSTALL_DIR}/ksysguard COMPONENT Devel) + diff --git a/ksysguard/processcore/Messages.sh b/ksysguard/processcore/Messages.sh new file mode 100755 index 000000000..4cfeec253 --- /dev/null +++ b/ksysguard/processcore/Messages.sh @@ -0,0 +1,2 @@ +#! /usr/bin/env bash +$XGETTEXT *.cpp -o $podir/processcore.pot diff --git a/ksysguard/processcore/process.cpp b/ksysguard/processcore/process.cpp new file mode 100644 index 000000000..673e0b24c --- /dev/null +++ b/ksysguard/processcore/process.cpp @@ -0,0 +1,246 @@ +/* This file is part of the KDE project + + Copyright (C) 2007 John Tapsell + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This 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 "process.h" + + +KSysGuard::Process::Process() { + clear(); +} +KSysGuard::Process::Process(long long _pid, long long _ppid, Process *_parent) { + clear(); + pid = _pid; + parent_pid = _ppid; + parent = _parent; +} + +QString KSysGuard::Process::niceLevelAsString() const { + // Just some rough heuristic to map a number to how nice it is + if( niceLevel == 0) return i18nc("Process Niceness", "Normal"); + if( niceLevel >= 10) return i18nc("Process Niceness", "Very low priority"); + if( niceLevel > 0) return i18nc("Process Niceness", "Low priority"); + if( niceLevel <= -10) return i18nc("Process Niceness", "Very high priority"); + if( niceLevel < 0) return i18nc("Process Niceness", "High priority"); + return QString(); //impossible; +} + +QString KSysGuard::Process::ioniceLevelAsString() const { + // Just some rough heuristic to map a number to how nice it is + if( ioniceLevel == 4) return i18nc("Process Niceness", "Normal"); + if( ioniceLevel >= 6) return i18nc("Process Niceness", "Very low priority"); + if( ioniceLevel > 4) return i18nc("Process Niceness", "Low priority"); + if( ioniceLevel <= 2) return i18nc("Process Niceness", "Very high priority"); + if( ioniceLevel < 4) return i18nc("Process Niceness", "High priority"); + return QString(); //impossible; + +} + +QString KSysGuard::Process::ioPriorityClassAsString() const { + switch( ioPriorityClass ) { + case None: return i18nc("Priority Class", "None"); + case RealTime: return i18nc("Priority Class", "Real Time"); + case BestEffort: return i18nc("Priority Class", "Best Effort"); + case Idle: return i18nc("Priority Class", "Idle"); + default: return i18nc("Priority Class", "Unknown"); + } +} + +QString KSysGuard::Process::translatedStatus() const { + switch( status ) { + case Running: return i18nc("process status", "running"); + case Sleeping: return i18nc("process status", "sleeping"); + case DiskSleep: return i18nc("process status", "disk sleep"); + case Zombie: return i18nc("process status", "zombie"); + case Stopped: return i18nc("process status", "stopped"); + case Paging: return i18nc("process status", "paging"); + default: return i18nc("process status", "unknown"); + } +} + +QString KSysGuard::Process::schedulerAsString() const { + switch( scheduler ) { + case Fifo: return i18nc("Scheduler", "FIFO"); + case RoundRobin: return i18nc("Scheduler", "Round Robin"); + case Batch: return i18nc("Scheduler", "Batch"); + default: return QString(); + } +} + +void KSysGuard::Process::clear() { + pid = 0; + parent_pid = 0; + uid = 0; + gid = -1; + suid = euid = fsuid = -1; + sgid = egid = fsgid = -1; + tracerpid = 0; + userTime = -1; + sysTime = -1; + userUsage=0; + sysUsage=0; + totalUserUsage=0; + totalSysUsage=0; + numChildren=0; + niceLevel=0; + vmSize=0; + vmRSS = 0; + vmURSS = 0; + status=OtherStatus; + parent = NULL; + ioPriorityClass = None; + ioniceLevel = -1; + scheduler = Other; + changes = Process::Nothing; +} +void KSysGuard::Process::setLogin(QString _login) { + if(login == _login) return; + login = _login; + changes |= Process::Login; +} +void KSysGuard::Process::setUid(long long _uid) { + if(uid == _uid) return; + uid = _uid; + changes |= Process::Uids; +} +void KSysGuard::Process::setEuid(long long _euid) { + if(euid == _euid) return; + euid = _euid; + changes |= Process::Uids; +} +void KSysGuard::Process::setSuid(long long _suid) { + if(suid == _suid) return; + suid = _suid; + changes |= Process::Uids; +} +void KSysGuard::Process::setFsuid(long long _fsuid) { + if(fsuid == _fsuid) return; + fsuid = _fsuid; + changes |= Process::Uids; +} + +void KSysGuard::Process::setGid(long long _gid) { + if(gid == _gid) return; + gid = _gid; + changes |= Process::Gids; +} +void KSysGuard::Process::setEgid(long long _egid) { + if(egid == _egid) return; + egid = _egid; + changes |= Process::Gids; +} +void KSysGuard::Process::setSgid(long long _sgid) { + if(sgid == _sgid) return; + sgid = _sgid; + changes |= Process::Gids; +} +void KSysGuard::Process::setFsgid(long long _fsgid) { + if(fsgid == _fsgid) return; + fsgid = _fsgid; + changes |= Process::Gids; +} + +void KSysGuard::Process::setTracerpid(long long _tracerpid) { + if(tracerpid == _tracerpid) return; + tracerpid = _tracerpid; + changes |= Process::Tracerpid; +} +void KSysGuard::Process::setTty(QByteArray _tty) { + if(tty == _tty) return; + tty = _tty; + changes |= Process::Tty; +} +void KSysGuard::Process::setUserTime(long long _userTime) { + userTime = _userTime; +} +void KSysGuard::Process::setSysTime(long long _sysTime) { + sysTime = _sysTime; +} +void KSysGuard::Process::setUserUsage(int _userUsage) { + if(userUsage == _userUsage) return; + userUsage = _userUsage; + changes |= Process::Usage; +} +void KSysGuard::Process::setSysUsage(int _sysUsage) { + if(sysUsage == _sysUsage) return; + sysUsage = _sysUsage; + changes |= Process::Usage; +} +void KSysGuard::Process::setTotalUserUsage(int _totalUserUsage) { + if(totalUserUsage == _totalUserUsage) return; + totalUserUsage = _totalUserUsage; + changes |= Process::TotalUsage; +} +void KSysGuard::Process::setTotalSysUsage(int _totalSysUsage) { + if(totalSysUsage == _totalSysUsage) return; + totalSysUsage = _totalSysUsage; + changes |= Process::TotalUsage; +} +void KSysGuard::Process::setNiceLevel(int _niceLevel) { + if(niceLevel == _niceLevel) return; + niceLevel = _niceLevel; + changes |= Process::NiceLevels; +} +void KSysGuard::Process::setscheduler(Scheduler _scheduler) { + if(scheduler == _scheduler) return; + scheduler = _scheduler; + changes |= Process::NiceLevels; +} +void KSysGuard::Process::setIoPriorityClass(IoPriorityClass _ioPriorityClass) { + if(ioPriorityClass == _ioPriorityClass) return; + ioPriorityClass = _ioPriorityClass; + changes |= Process::NiceLevels; +} +void KSysGuard::Process::setIoniceLevel(int _ioniceLevel) { + if(ioniceLevel == _ioniceLevel) return; + ioniceLevel = _ioniceLevel; + changes |= Process::NiceLevels; +} +void KSysGuard::Process::setVmSize(long _vmSize) { + if(vmSize == _vmSize) return; + vmSize = _vmSize; + changes |= Process::VmSize; +} +void KSysGuard::Process::setVmRSS(long _vmRSS) { + if(vmRSS == _vmRSS) return; + vmRSS = _vmRSS; + changes |= Process::VmRSS; +} +void KSysGuard::Process::setVmURSS(long _vmURSS) { + if(vmURSS == _vmURSS) return; + vmURSS = _vmURSS; + changes |= Process::VmURSS; +} +void KSysGuard::Process::setName(QString _name) { + if(name == _name) return; + name = _name; + changes |= Process::Name; +} +void KSysGuard::Process::setCommand(QString _command) { + if(command == _command) return; + command = _command; + changes |= Process::Command; +} +void KSysGuard::Process::setStatus(ProcessStatus _status) { + if(status == _status) return; + status = _status; + changes |= Process::Status; +} + diff --git a/ksysguard/processcore/process.h b/ksysguard/processcore/process.h new file mode 100644 index 000000000..a1f4c6016 --- /dev/null +++ b/ksysguard/processcore/process.h @@ -0,0 +1,160 @@ +/* This file is part of the KDE project + + Copyright (C) 2007 John Tapsell + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This 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 PROCESS_H_ +#define PROCESS_H_ + +#include + +#include +#include +#include + +#include + + +namespace KSysGuard +{ + + class KDE_EXPORT Process { + public: + enum ProcessStatus { Running, Sleeping, DiskSleep, Zombie, Stopped, Paging, OtherStatus }; + enum IoPriorityClass { None, RealTime, BestEffort, Idle }; + enum Scheduler { Other = 0, Fifo, RoundRobin, Batch }; + Process(); + Process(long long _pid, long long _ppid, Process *_parent); + + long pid; ///The system's ID for this process. 1 for init. 0 for our virtual 'parent of init' process used just for convience. + long parent_pid; ///The system's ID for the parent of this process. 0 for init. + + /** A guaranteed NON-NULL pointer for all real processes to the parent process except for the fake process with pid 0. + * The Parent's pid is the same value as the parent_pid. The parent process will be also pointed + * to by ProcessModel::mPidToProcess to there is no need to worry about mem management in using parent. + * For init process, parent will point to a (fake) process with pid 0 to simplify things. + * For the fake process, this will point to NULL + */ + Process *parent; + + void setLogin(QString _login); ///The user login name. Only used for processes on remote machines. Otherwise use uid to get the name + void setUid(long long _uid); ///The user id that the process is running as + void setEuid(long long _euid); ///The effective user id that the process is running as + void setSuid(long long _suid); ///The set user id that the process is running as + void setFsuid(long long _fsuid); ///The file system user id that the process is running as. + + void setGid(long long _gid); ///The process group id that the process is running as + void setEgid(long long _egid); ///The effective group id that the process is running as + void setSgid(long long _sgid); ///The set group id that the process is running as + void setFsgid(long long _fsgid); ///The file system group id that the process is running as + + void setTracerpid(long long _tracerpid); ///If this is being debugged, this is the process that is debugging it + void setTty(QByteArray _tty); /// The name of the tty the process owns + void setUserTime(long long _userTime); ///The time, in 100ths of a second, spent in total on user calls. -1 if not known + void setSysTime(long long _sysTime); ///The time, in 100ths of a second, spent in total on system calls. -1 if not known + void setUserUsage(int _userUsage); ///Percentage (0 to 100). It might be more than 100% on multiple cpu core systems + void setSysUsage(int _sysUsage); ///Percentage (0 to 100). It might be more than 100% on multiple cpu core systems + void setTotalUserUsage(int _totalUserUsage); ///Percentage (0 to 100) from the sum of itself and all its children recursively. If there's no children, it's equal to userUsage. It might be more than 100% on multiple cpu core systems + void setTotalSysUsage(int _totalSysUsage); ///Percentage (0 to 100) from the sum of itself and all its children recursively. If there's no children, it's equal to sysUsage. It might be more than 100% on multiple cpu core systems + void setNiceLevel(int _niceLevel); ///If Scheduler = Other, niceLevel is the niceness (-20 to 20) of this process. A lower number means a higher priority. Otherwise sched priority (1 to 99) + void setscheduler(Scheduler _scheduler); ///The scheduler this process is running in. See man sched_getscheduler for more info + void setIoPriorityClass(IoPriorityClass _ioPriorityClass); /// The IO priority class. See man ionice for detailed information. + void setIoniceLevel(int _ioniceLevel); ///IO Niceness (0 to 7) of this process. A lower number means a higher io priority. -1 if not known or not applicable because ioPriorityClass is Idle or None + void setVmSize(long _vmSize); ///Virtual memory size in KiloBytes, including memory used, mmap'ed files, graphics memory etc, + void setVmRSS(long _vmRSS); ///Physical memory used by the process and its shared libraries. If the process and libraries are swapped to disk, this could be as low as 0 + void setVmURSS(long _vmURSS); ///Physical memory used only by the process, and not counting the code for shared libraries. Set to -1 if unknown + void setName(QString _name); ///The name (e.g. "ksysguard", "konversation", "init") + void setCommand(QString _command); ///The command the process was launched with + void setStatus( ProcessStatus _status); ///Whether the process is running/sleeping/etc + + + + QString login; + long long uid; + long long euid; + long long suid; + long long fsuid; + + long long gid; + long long egid; + long long sgid; + long long fsgid; + + long long tracerpid; + QByteArray tty; + long long userTime; + long long sysTime; + int userUsage; + int sysUsage; + int totalUserUsage; + int totalSysUsage; + unsigned long numChildren; + int niceLevel; + Scheduler scheduler; + IoPriorityClass ioPriorityClass; + int ioniceLevel; + long vmSize; + long vmRSS; + long vmURSS; + QString name; + QString command; + ProcessStatus status; + + QList children; ///A list of all the direct children that the process has. Children of children are not listed here, so note that children_pids <= numChildren + QTime timeKillWasSent; /// This is usually a NULL time. When trying to kill a process, this is the time that the kill signal was sent to the process. + + QString translatedStatus() const; /// Returns a translated string of the status. e.g. "Running" etc + QString niceLevelAsString() const; /// Returns a simple translated string of the nice priority. e.g. "Normal", "High", etc + QString ioniceLevelAsString() const; /// Returns a simple translated string of the io nice priority. e.g. "Normal", "High", etc + QString ioPriorityClassAsString() const; /// Returns a translated string of the io nice class. i.e. "None", "Real Time", "Best Effort", "Idle" + QString schedulerAsString() const; /// Returns a translated string of the scheduler class. e.g. "FIFO", "Round Robin", "Batch" + + int index; /// Each process has a parent process. Each sibling has a unique number to identify it under that parent. This is that number. + + /** An enum to keep track of what changed since the last update. Note that we + * the maximum we can use is 0x4000, so some of the enums represent multiple variables + */ + enum Change { + Nothing = 0x0, + Uids = 0x1, + Gids = 0x2, + Tracerpid = 0x4, + Tty = 0x8, + Usage = 0x10, + TotalUsage = 0x20, + NiceLevels = 0x40, + VmSize = 0x80, + VmRSS = 0x100, + VmURSS = 0x200, + Name = 0x400, + Command = 0x800, + Status = 0x1000, + Login = 0x2000 + }; + Q_DECLARE_FLAGS(Changes, Change) + + Changes changes; /** A QFlags representing what has changed */ + + + private: + void clear(); + }; + Q_DECLARE_OPERATORS_FOR_FLAGS(Process::Changes) +} + +#endif diff --git a/ksysguard/processcore/processes.cpp b/ksysguard/processcore/processes.cpp new file mode 100644 index 000000000..d62063837 --- /dev/null +++ b/ksysguard/processcore/processes.cpp @@ -0,0 +1,398 @@ +/* This file is part of the KDE project + + Copyright (C) 2007 John Tapsell + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This 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 "processes.h" +#include "processes_base_p.h" +#include "processes_local_p.h" +#include "processes_remote_p.h" +#include "process.h" + +#include +#include +#include + +#include +#include +#include +#include + +//for sysconf +#include + +/* if porting to an OS without signal.h please #define SIGTERM to something */ +#include + + +namespace KSysGuard +{ + Processes::StaticPrivate *Processes::d2 = 0; + + class Processes::Private + { + public: + Private() { mAbstractProcesses = 0; mProcesses.insert(0, &mFakeProcess); mElapsedTimeCentiSeconds = -1; ref=1; } + ~Private(); + + QSet mToBeProcessed; + QSet mProcessedLastTime; + + QHash mProcesses; //This must include mFakeProcess at pid 0 + QList mListProcesses; //A list of the processes. Does not include mFakeProcesses + Process mFakeProcess; //A fake process with pid 0 just so that even init points to a parent + + AbstractProcesses *mAbstractProcesses; //The OS specific code to get the process information + QTime mLastUpdated; //This is the time we last updated. Used to calculate cpu usage. + long mElapsedTimeCentiSeconds; //The number of centiseconds (100ths of a second) that passed since the last update + + int ref; //Reference counter. When it reaches 0, delete. + }; + + class Processes::StaticPrivate + { + public: + StaticPrivate() { processesLocal = 0; ref =1; } + Processes *processesLocal; + QHash processesRemote; + int ref; //Reference counter. When it reaches 0, delete. + }; + +Processes::Private::~Private() { + foreach(Process *process, mProcesses) { + if(process != &mFakeProcess) + delete process; + } + mProcesses.clear(); + mListProcesses.clear(); + delete mAbstractProcesses; + mAbstractProcesses = NULL; +} + +Processes *Processes::getInstance(const QString &host) { //static + if(!d2) { + d2 = new StaticPrivate(); + } else { + d2->ref++; + } + if(host.isEmpty()) { + //Localhost processes + if(!d2->processesLocal) { + KGlobal::locale()->insertCatalog("processcore"); //Make sure we include the translation stuff. This needs to be run before any i18n call here + d2->processesLocal = new Processes(new ProcessesLocal()); + } else { + d2->processesLocal->d->ref++; + } + return d2->processesLocal; + } else { + Processes *processes = d2->processesRemote.value(host, NULL); + if( !processes ) { + //connect to it + KGlobal::locale()->insertCatalog("processcore"); //Make sure we include the translation stuff. This needs to be run before any i18n call here + ProcessesRemote *remote = new ProcessesRemote(host); + processes = new Processes( remote ); + d2->processesRemote.insert(host, processes); + connect(remote, SIGNAL(runCommand(const QString &, int )), processes, SIGNAL(runCommand(const QString&, int))); + } else { + processes->d->ref++; + } + return processes; + } +} + +void Processes::returnInstance(const QString &host) { //static + if(!d2) { + kDebug() << "Internal error - static class does not exist"; + return; + } + if(host.isEmpty()) { + //Localhost processes + if(!d2->processesLocal) { + //Serious error. Returning instance we don't have. + kDebug() << "Internal error - returning instance we do not have"; + return; + } else { + if(--(d2->processesLocal->d->ref) == 0) { + delete d2->processesLocal; + d2->processesLocal = NULL; + } + } + } else { + Processes *processes = d2->processesRemote.value(host, NULL); + if( !processes ) { + kDebug() << "Internal error - returning instance we do not have"; + return; + } else { + if(--(processes->d->ref) == 0) { + delete processes; + d2->processesRemote.remove(host); + } + } + } + if(--(d2->ref) == 0) { + delete d2; + d2 = NULL; + } + +} +Processes::Processes(AbstractProcesses *abstractProcesses) : d(new Private()) +{ + d->mAbstractProcesses = abstractProcesses; + connect( abstractProcesses, SIGNAL( processesUpdated() ), SLOT( processesUpdated() )); +} + +Processes::~Processes() +{ + delete d; +} +Process *Processes::getProcess(long pid) const +{ + return d->mProcesses.value(pid); +} + +QList Processes::getAllProcesses() const +{ + return d->mListProcesses; +} +bool Processes::updateProcess( Process *ps, long ppid, bool onlyReparent) +{ + Process *parent = d->mProcesses.value(ppid); + Q_ASSERT(parent); //even init has a non-null parent - the mFakeProcess + + if(ps->parent != parent) { + emit beginMoveProcess(ps, parent/*new parent*/); + //Processes has been reparented + Process *p = ps; + do { + p = p->parent; + p->numChildren--; + } while (p->pid!= 0); + ps->parent->children.removeAll(ps); + ps->parent = parent; //the parent has changed + parent->children.append(ps); + p = ps; + do { + p = p->parent; + p->numChildren++; + } while (p->pid!= 0); + emit endMoveProcess(); + } + if(onlyReparent) + return true; + + ps->parent = parent; + ps->parent_pid = ppid; + + //Now we can actually get the process info + long oldUserTime = ps->userTime; + long oldSysTime = ps->sysTime; + ps->changes = Process::Nothing; + bool success = d->mAbstractProcesses->updateProcessInfo(ps->pid, ps); + + //Now we have the process info. Calculate the cpu usage and total cpu usage for itself and all its parents + if(oldUserTime != -1 && d->mElapsedTimeCentiSeconds!= 0) { //Update the user usage and sys usage +#ifndef Q_OS_NETBSD + ps->setUserUsage((int)(((ps->userTime - oldUserTime)*100.0 + 0.5) / d->mElapsedTimeCentiSeconds)); + ps->setSysUsage((int)(((ps->sysTime - oldSysTime)*100.0 + 0.5) / d->mElapsedTimeCentiSeconds)); +#endif + ps->setTotalUserUsage(ps->userUsage); + ps->setTotalSysUsage(ps->sysUsage); + if(ps->userUsage != 0 || ps->sysUsage != 0) { + Process *p = ps->parent; + while(p->pid != 0) { + p->totalUserUsage += ps->userUsage; + p->totalSysUsage += ps->sysUsage; + emit processChanged(p, true); + p= p->parent; + } + } + } + + emit processChanged(ps, false); + + return success; + +} +bool Processes::addProcess(long pid, long ppid) +{ + Process *parent = d->mProcesses.value(ppid); + if(!parent) return false; //How can this be? + //it's a new process - we need to set it up + Process *ps = new Process(pid, ppid, parent); + + emit beginAddProcess(ps); + + d->mProcesses.insert(pid, ps); + + ps->index = d->mListProcesses.count(); + d->mListProcesses.append(ps); + + ps->parent->children.append(ps); + Process *p = ps; + do { + p = p->parent; + p->numChildren++; + } while (p->pid!= 0); + ps->parent_pid = ppid; + + //Now we can actually get the process info + bool success = d->mAbstractProcesses->updateProcessInfo(pid, ps); + emit endAddProcess(); + return success; + +} +bool Processes::updateOrAddProcess( long pid) +{ + long ppid = d->mAbstractProcesses->getParentPid(pid); + + if(d->mToBeProcessed.contains(ppid)) { + //Make sure that we update the parent before we update this one. Just makes things a bit easier. + d->mToBeProcessed.remove(ppid); + d->mProcessedLastTime.remove(ppid); //It may or may not be here - remove it if it is there + updateOrAddProcess(ppid); + } + + Process *ps = d->mProcesses.value(pid, 0); + if(!ps) + return addProcess(pid, ppid); + else + return updateProcess(ps, ppid); +} + +void Processes::updateAllProcesses( long updateDurationMS ) +{ + if(d->mElapsedTimeCentiSeconds == -1) { + //First time update has been called + d->mLastUpdated.start(); + d->mElapsedTimeCentiSeconds = 0; + } else { + if(d->mLastUpdated.elapsed() < updateDurationMS) //don't update more often than the time given + return; + d->mElapsedTimeCentiSeconds = d->mLastUpdated.restart() / 10; + } + + d->mAbstractProcesses->updateAllProcesses(); +} + +void Processes::processesUpdated() { + d->mToBeProcessed = d->mAbstractProcesses->getAllPids(); + + QSet beingProcessed(d->mToBeProcessed); //keep a copy so that we can replace mProcessedLastTime with this at the end of this function + + long pid; + { + QMutableSetIterator i(d->mToBeProcessed); + while( i.hasNext()) { + pid = i.next(); + i.remove(); + d->mProcessedLastTime.remove(pid); //It may or may not be here - remove it if it is there + updateOrAddProcess(pid); //This adds the process or changes an extisting one + i.toFront(); //we can remove entries from this set elsewhere, so our iterator might be invalid. reset it back to the start of the set + } + } + { + QMutableSetIterator i(d->mProcessedLastTime); + while( i.hasNext()) { + //We saw these pids last time, but not this time. That means we have to delete them now + pid = i.next(); + i.remove(); + deleteProcess(pid); + i.toFront(); + } + } + + d->mProcessedLastTime = beingProcessed; //update the set for next time this function is called + return; +} + + +void Processes::deleteProcess(long pid) +{ + Q_ASSERT(pid > 0); + + Process *process = d->mProcesses.value(pid); + foreach( Process *it, process->children) { + d->mProcessedLastTime.remove(it->pid); + deleteProcess(it->pid); + } + + emit beginRemoveProcess(process); + + d->mProcesses.remove(pid); + d->mListProcesses.removeAll(process); + process->parent->children.removeAll(process); + Process *p = process; + do { + p = p->parent; + p->numChildren--; + } while (p->pid!= 0); + + int i=0; + foreach( Process *it, d->mListProcesses ) { + if(it->index > process->index) + it->index--; + Q_ASSERT(it->index == i++); + } + + delete process; + emit endRemoveProcess(); +} + + +bool Processes::killProcess(long pid) { + return sendSignal(pid, SIGTERM); +} + +bool Processes::sendSignal(long pid, int sig) { + return d->mAbstractProcesses->sendSignal(pid, sig); +} + +bool Processes::setNiceness(long pid, int priority) { + return d->mAbstractProcesses->setNiceness(pid, priority); +} + +bool Processes::setScheduler(long pid, KSysGuard::Process::Scheduler priorityClass, int priority) { + return d->mAbstractProcesses->setScheduler(pid, priorityClass, priority); +} + +bool Processes::setIoNiceness(long pid, KSysGuard::Process::IoPriorityClass priorityClass, int priority) { + return d->mAbstractProcesses->setIoNiceness(pid, priorityClass, priority); +} + +bool Processes::supportsIoNiceness() { + return d->mAbstractProcesses->supportsIoNiceness(); +} + +long long Processes::totalPhysicalMemory() { + return d->mAbstractProcesses->totalPhysicalMemory(); +} + +long Processes::numberProcessorCores() { + return d->mAbstractProcesses->numberProcessorCores(); +} + +void Processes::answerReceived( int id, const QList& answer ) { + KSysGuard::ProcessesRemote *processes = dynamic_cast(d->mAbstractProcesses); + if(processes) + processes->answerReceived(id, answer); +} + +} +#include "processes.moc" + diff --git a/ksysguard/processcore/processes.h b/ksysguard/processcore/processes.h new file mode 100644 index 000000000..c5f80ad51 --- /dev/null +++ b/ksysguard/processcore/processes.h @@ -0,0 +1,224 @@ +/* This file is part of the KDE project + + Copyright (C) 2007 John Tapsell + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This 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 PROCESSES_H_ +#define PROCESSES_H_ + +#include + +#include "process.h" +#include + +namespace KSysGuard +{ + class AbstractProcesses; + /** + * This class retrieves the processes currently running in an OS independent way. + * + * To use, do something like: + * + * \code + * #include + * #include + * + * KSysGuard::Processes *processes = KSysGuard::Processes::getInstance(); + * QHash processlist = processes->getProcesses(); + * foreach( Process * process, processlist) { + * kDebug() << "Process with pid " << process->pid << " is called " << process->name; + * } + * KSysGuard::Processes::returnInstance(processes); + * processes = NULL; + * \endcode + * + * @author John Tapsell + */ + class KDE_EXPORT Processes : public QObject + { + Q_OBJECT + + public: + /** + * Singleton pattern to return the instance associated with @p host. + * Leave as the default for the current machine + */ + static Processes *getInstance(const QString &host = QString()); + /** + * Call when you are finished with the Processes pointer from getInstance. + * The pointer from getInstance may not be valid after calling this. + * This is reference counted - once all the instances are returned, the object is deleted + */ + static void returnInstance(const QString &host = QString()); + + /** + * Update all the process information. After calling this, /proc or equivalent is scanned and + * the signals processChanged, etc are emitted. + * + * Set updateDuration to whatever time period that you update, in milliseconds. + * For example, if you update every 2000ms, set this to 2000. That way it won't update + * more often than needed + */ + void updateAllProcesses(long updateDurationMS = 0); + /** + * Return information for one specific process. call getProcess(0) to get the + * fake process used as the top most parent for all processes. + * This doesn't fetch any new information and so returns almost instantly. + * Call updateAllProcesses() to actually fetch the process information. + */ + Process *getProcess(long pid) const; + + /** + * Kill the specified process. You may not have the privillage to kill the process. + * The process may also chose to ignore the command. Send the SIGKILL signal to kill + * the process immediately. You may lose any unsaved data. + * + * @returns Successful or not in killing the process + */ + bool killProcess(long pid); + + /** + * Send the specified named POSIX signal to the process given. + * + * For example, to indicate for process 324 to STOP do: + * \code + * #include + * ... + * + * KSysGuard::Processes::sendSignal(23, SIGSTOP); + * \endcode + * + */ + bool sendSignal(long pid, int sig); + + /** + * Set the priority for a process. This is from 19 (very nice, lowest priority) to + * -20 (highest priority). The default value for a process is 0. + * + * @return false if you do not have permission to set the priority + */ + bool setNiceness(long pid, int priority); + + /** + * Set the scheduler for a process. This is defined according to POSIX.1-2001 + * See "man sched_setscheduler" for more information. + * + * @p priorityClass One of SCHED_FIFO, SCHED_RR, SCHED_OTHER, and SCHED_BATCH + * @p priority Set to 0 for SCHED_OTHER and SCHED_BATCH. Between 1 and 99 for SCHED_FIFO and SCHED_RR + * @return false if you do not have permission to set the priority + */ + bool setScheduler(long pid, KSysGuard::Process::Scheduler priorityClass, int priority); + + /** + * Set the io priority for a process. This is from 7 (very nice, lowest io priority) to + * 0 (highest priority). The default value is determined as: io_nice = (cpu_nice + 20) / 5. + * + * @return false if you do not have permission to set the priority + */ + bool setIoNiceness(long pid, KSysGuard::Process::IoPriorityClass priorityClass, int priority); + + /** + * Returns true if ionice is supported on this system + */ + bool supportsIoNiceness(); + + /** + * Return the internal pointer of all the processes. The order of the processes + * is guaranteed to never change. Call updateAllProcesses first to actually + * update the information. + */ + QList< Process *> getAllProcesses() const; + + /** + * Return the total amount of physical memory in KB. This is fast (just a system call) + * Returns 0 on error + */ + long long totalPhysicalMemory(); + + /** + * Return the number of processor cores enabled. + * (A system can disable procesors. Disabled processors are not counted here). + * This is fast (just a system call) */ + long numberProcessorCores(); + + public Q_SLOTS: + /** The abstract processes has updated its list of processes */ + void processesUpdated(); + + Q_SIGNALS: + /** The data for a process has changed. + * if @p onlyTotalCpu is set, only the total cpu usage has been updated. + * process->changes contains a bit field indicating what has changed since the last time this was emitted + * for this process + */ + void processChanged( KSysGuard::Process *process, bool onlyTotalCpu); + /** + * This indicates we are about to add a process in the model. + * The process already has the pid, ppid and tree_parent set up. + */ + void beginAddProcess( KSysGuard::Process *process); + /** + * We have finished inserting a process + */ + void endAddProcess(); + /** + * This indicates we are about to remove a process in the model. Emit the appropriate signals + */ + void beginRemoveProcess( KSysGuard::Process *process); + /** + * We have finished removing a process + */ + void endRemoveProcess(); + /** + * This indicates we are about move a process from one parent to another. + */ + void beginMoveProcess(KSysGuard::Process *process, KSysGuard::Process *new_parent); + /** + * We have finished moving the process + */ + void endMoveProcess(); + protected: + Processes(AbstractProcesses *abstractProcesses); + ~Processes(); + class Private; + Private *d; + class StaticPrivate; + static StaticPrivate *d2; + private: + bool updateOrAddProcess( long pid); + inline void deleteProcess(long pid); + bool updateProcess( Process *process, long ppid, bool onlyReparent = false); + bool addProcess(long pid, long ppid); + + + Q_SIGNALS: + /** For a remote machine, we rely on being able to communicate with ksysguardd. + * This must be dealt with by the program including this widget. It must listen to our + * 'runCommand' signal, and run the given command, with the given id. */ + void runCommand(const QString &command, int id); + + public: + /** For a remote machine, we rely on being able to communicate with ksysguardd. + * The programming using this must call this slot when an answer is received from ksysguardd, + * in response to a runCommand request. The id identifies the answer */ + void answerReceived( int id, const QList& answer ); + + }; +} +#endif diff --git a/ksysguard/processcore/processes_base_p.cpp b/ksysguard/processcore/processes_base_p.cpp new file mode 100644 index 000000000..ea8be5623 --- /dev/null +++ b/ksysguard/processcore/processes_base_p.cpp @@ -0,0 +1,22 @@ +/* This file is part of the KDE project + + Copyright (C) 2007 John Tapsell + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This 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 "processes_base_p.moc" diff --git a/ksysguard/processcore/processes_base_p.h b/ksysguard/processcore/processes_base_p.h new file mode 100644 index 000000000..5acd9568b --- /dev/null +++ b/ksysguard/processcore/processes_base_p.h @@ -0,0 +1,139 @@ +/* This file is part of the KDE project + + Copyright (C) 2007 John Tapsell + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This 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 PROCESSES_BASE_P_H +#define PROCESSES_BASE_P_H + +#include +#include + +namespace KSysGuard +{ + class Process; + /** + * This class contains the specific code to get the processes from the given host. + * + * To port this to other operating systems you need to make a processes_(osname).cpp file + * which implements all of the function below. If you need private functions/variables etc put them in + * the Private class. + * + * @author John Tapsell + */ + class AbstractProcesses : public QObject + { + Q_OBJECT + + public: + + AbstractProcesses() {} + virtual ~AbstractProcesses() {} + /** + * To get information about processes, this will be the first function called. + */ + virtual QSet getAllPids() = 0; + /** + * For each of the pids that getAllPids() returns, getParentPid will be called. This is used to setup the tree structure. + * For a particular pid, this is guaranteed to be called before updateProcessInfo for that pid. + * However this may be called several times in a row before the updateProcessInfo is called, so be careful + * if you want to try to preserve state in Private. + */ + virtual long getParentPid(long pid) = 0; + /** + * This will be called for every pid, after getParentPid() has been called for the same parameter. + * + * The process->pid process->ppid and process->parent are all guaranteed to be filled in correctly and process->parent + * will be non null. + */ + virtual bool updateProcessInfo(long pid, Process *process) = 0; + /** + * Send the specified named POSIX signal to the process given. + * + * For example, to indicate for process 324 to STOP do: + * \code + * #include + * ... + * + * KSysGuard::Processes::sendSignal(23, SIGSTOP); + * \endcode + * + */ + virtual bool sendSignal(long pid, int sig) = 0; + + /** + * Set the priority for a process. For the normal scheduler, this is usually from 19 + * (very nice, lowest priority) to -20 (highest priority). The default value for a process is 0. + * + * This has no effect if the scheduler is not the normal one (SCHED_OTHER) + * + * @return false if you do not have permission to set the priority + */ + virtual bool setNiceness(long pid, int priority) = 0; + + /** + * Set the scheduler for a process. This is defined according to POSIX.1-2001 + * See "man sched_setscheduler" for more information. + * + * @p priorityClass One of SCHED_FIFO, SCHED_RR, SCHED_OTHER, and SCHED_BATCH + * @p priority Set to 0 for SCHED_OTHER and SCHED_BATCH. Between 1 and 99 for SCHED_FIFO and SCHED_RR + * @return false if you do not have permission to set the priority + */ + virtual bool setScheduler(long pid, int priorityClass, int priority) = 0; + + /** + * Return the total amount of physical memory in KB. This is fast (just a system call) + * Returns 0 on error + */ + virtual long long totalPhysicalMemory() = 0; + + /** + * Set the io priority for a process. This is from 7 (very nice, lowest io priority) to + * 0 (highest priority). The default value is determined as: io_nice = (cpu_nice + 20) / 5. + * + * @return false if you do not have permission to set the priority + */ + virtual bool setIoNiceness(long pid, int priorityClass, int priority) = 0; + + /** + * Returns true if ionice is supported on this system + */ + virtual bool supportsIoNiceness() = 0; + + /** + * Return the number of processor cores enabled. + * (A system can disable procesors. Disabled processors are not counted here). + * This is fast (just a system call) */ + virtual long numberProcessorCores() = 0; + + /** + * Get all the current process information from the machine. When done, emit updateAllProcesses(). + */ + virtual void updateAllProcesses() = 0; + + Q_SIGNALS: + /** + * This is emitted when the processes have been updated, and the view should be refreshed + */ + void processesUpdated(); + + }; +} + +#endif // PROCESSES_BASE_P_H diff --git a/ksysguard/processcore/processes_freebsd_p.cpp b/ksysguard/processcore/processes_freebsd_p.cpp new file mode 100644 index 000000000..b5fc34986 --- /dev/null +++ b/ksysguard/processcore/processes_freebsd_p.cpp @@ -0,0 +1,307 @@ +/* This file is part of the KDE project + Copyright (C) 2007 Manolo Valdes + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This 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 "processes_local_p.h" +#include "process.h" + +#include + +#include + +#include +#include +#include +#include +#include +#if defined(__DragonFly__) +#include +#include +#endif +#include +#include +#include +#include + + + +namespace KSysGuard +{ + + class ProcessesLocal::Private + { + public: + Private() {;} + ~Private() {;} + inline bool readProc(long pid, struct kinfo_proc *p); + inline void readProcStatus(struct kinfo_proc *p, Process *process); + inline void readProcStat(struct kinfo_proc *p, Process *process); + inline void readProcStatm(struct kinfo_proc *p, Process *process); + inline bool readProcCmdline(long pid, Process *process); + }; + +bool ProcessesLocal::Private::readProc(long pid, struct kinfo_proc *p) +{ + int mib[4]; + size_t len; + + mib[0] = CTL_KERN; + mib[1] = KERN_PROC; + mib[2] = KERN_PROC_PID; + mib[3] = pid; + + len = sizeof (struct kinfo_proc); + if (sysctl(mib, 4, p, &len, NULL, 0) == -1 || !len) + return false; + return true; +} + +void ProcessesLocal::Private::readProcStatus(struct kinfo_proc *p, Process *process) +{ + process->setUid(0); + process->setGid(0); + process->setTracerpid(0); + + +#if defined(__FreeBSD__) && __FreeBSD_version >= 500015 + process->setUid(p->ki_uid); + process->setGid(p->ki_pgid); + process->setName(QString(p->ki_comm ? p->ki_comm : "????")); +#elif defined(__DragonFly__) && __DragonFly_version >= 190000 + process->setUid(p->kp_uid); + process->setGid(p->kp_pgid); + process->setName(QString(p->kp_comm ? p->kp_comm : "????")); +#else + process->setUid(p->kp_eproc.e_ucred.cr_uid); + process->setGid(p->kp_eproc.e_pgid); +#endif +} + +void ProcessesLocal::Private::readProcStat(struct kinfo_proc *p, Process *ps) +{ + int status; + struct rusage pru; +#if defined(__FreeBSD__) && __FreeBSD_version >= 500015 + ps->setUserTime(p->ki_runtime / 10000); + ps->setNiceLevel(p->ki_nice); + ps->setVmSize(p->ki_size); + ps->setVmRSS(p->ki_rssize * getpagesize()); + status = p->ki_stat; +#elif defined(__DragonFly__) && __DragonFly_version >= 190000 + if (!getrusage(p->kp_pid, &pru)) { + errx(1, "failed to get rusage info"); + } + ps->setUserTime(pru.ru_utime.tv_usec / 1000); /*p_runtime / 1000*/ + ps->setNiceLevel(p->kp_nice); + ps->setVmSize(p->kp_vm_map_size); + ps->setVmRSS(p->kp_vm_rssize * getpagesize()); + status = p->kp_stat; +#else + ps->setUserTime(p->kp_proc.p_rtime.tv_sec*100+p->kp_proc.p_rtime.tv_usec/100); + ps->setNiceLevel(p->kp_proc.p_nice); + ps->setVmSize(p->kp_eproc.e_vm.vm_map.size); + ps->setVmRSS(p->kp_eproc.e_vm.vm_rssize * getpagesize()); + status = p->kp_proc.p_stat; +#endif + ps->setSysTime(0); + +// "idle","run","sleep","stop","zombie" + switch( status ) { + case '0': + ps->setStatus(Process::DiskSleep); + break; + case '1': + ps->setStatus(Process::Running); + break; + case '2': + ps->setStatus(Process::Sleeping); + break; + case '3': + ps->setStatus(Process::Stopped); + break; + case '4': + ps->setStatus(Process::Zombie); + break; + default: + ps->setStatus(Process::OtherStatus); + break; + } +} + +void ProcessesLocal::Private::readProcStatm(struct kinfo_proc *p, Process *process) +{ +// TODO + +// unsigned long shared; +// process->setVmURSS(process->vmRSS - (shared * sysconf(_SC_PAGESIZE) / 1024)); +} + +bool ProcessesLocal::Private::readProcCmdline(long pid, Process *process) +{ + int mib[4]; + struct kinfo_proc p; + size_t buflen = 256; + char buf[256]; + + mib[0] = CTL_KERN; + mib[1] = KERN_PROC; + mib[2] = KERN_PROC_ARGS; + mib[3] = pid; + + if (sysctl(mib, 4, buf, &buflen, NULL, 0) == -1 || !buflen) + return false; + QString command = QString(buf); + + //cmdline seperates parameters with the NULL character + command = command.replace('\0', ' '); + process->setCommand(command.trimmed()); + + return true; +} + +ProcessesLocal::ProcessesLocal() : d(new Private()) +{ + +} + +long ProcessesLocal::getParentPid(long pid) { + long long ppid = 0; + struct kinfo_proc p; + if(d->readProc(pid, &p)) + { +#if defined(__FreeBSD__) && __FreeBSD_version >= 500015 + ppid = p.ki_ppid; +#elif defined(__DragonFly__) && __DragonFly_version >= 190000 + ppid = p.kp_ppid; +#else + ppid = p.kp_eproc.e_ppid; +#endif + } + return ppid; +} + +bool ProcessesLocal::updateProcessInfo( long pid, Process *process) +{ + struct kinfo_proc p; + if(!d->readProc(pid, &p)) return false; + d->readProcStat(&p, process); + d->readProcStatus(&p, process); + d->readProcStatm(&p, process); + if(!d->readProcCmdline(pid, process)) return false; + + return true; +} + +QSet ProcessesLocal::getAllPids( ) +{ + QSet pids; + int mib[3]; + size_t len; + size_t num; + struct kinfo_proc *p; + + mib[0] = CTL_KERN; + mib[1] = KERN_PROC; + mib[2] = KERN_PROC_ALL; + sysctl(mib, 3, NULL, &len, NULL, 0); + p = (kinfo_proc *) malloc(len); + sysctl(mib, 3, p, &len, NULL, 0); + + for (num = 0; num < len / sizeof(struct kinfo_proc); num++) + { +#if defined(__FreeBSD__) && __FreeBSD_version >= 500015 + long pid = p[num].ki_pid; + long long ppid = p[num].ki_ppid; +#elif defined(__DragonFly__) && __DragonFly_version >= 190000 + long pid = p[num].kp_pid; + long long ppid = p[num].kp_ppid; +#else + long pid = p[num].kp_proc.p_pid; + long long ppid = p[num].kp_eproc.e_ppid; +#endif + //skip all process with parent id = 0 but init + if(ppid == 0 && pid != 1) + continue; + pids.insert(pid); + } + free(p); + return pids; +} + +bool ProcessesLocal::sendSignal(long pid, int sig) { + if ( kill( (pid_t)pid, sig ) ) { + //Kill failed + return false; + } + return true; +} + +bool ProcessesLocal::setNiceness(long pid, int priority) { + if ( setpriority( PRIO_PROCESS, pid, priority ) ) { + //set niceness failed + return false; + } + return true; +} + +bool ProcessesLocal::setScheduler(long pid, int priorityClass, int priority) +{ + if(priorityClass == KSysGuard::Process::Other || priorityClass == KSysGuard::Process::Batch) + priority = 0; + if(pid <= 0) return false; // check the parameters + struct sched_param params; + params.sched_priority = priority; + switch(priorityClass) { + case (KSysGuard::Process::Other): + return (sched_setscheduler( pid, SCHED_OTHER, ¶ms) == 0); + case (KSysGuard::Process::RoundRobin): + return (sched_setscheduler( pid, SCHED_RR, ¶ms) == 0); + case (KSysGuard::Process::Fifo): + return (sched_setscheduler( pid, SCHED_FIFO, ¶ms) == 0); +#ifdef SCHED_BATCH + case (KSysGuard::Process::Batch): + return (sched_setscheduler( pid, SCHED_BATCH, ¶ms) == 0); +#endif + default: + return false; + } +} + +bool ProcessesLocal::setIoNiceness(long pid, int priorityClass, int priority) { + return false; //Not yet supported +} + +bool ProcessesLocal::supportsIoNiceness() { + return false; +} + +long long ProcessesLocal::totalPhysicalMemory() { + + size_t Total; + size_t len; + len = sizeof (Total); + sysctlbyname("hw.physmem", &Total, &len, NULL, 0); + return Total /= 1024; +} + +ProcessesLocal::~ProcessesLocal() +{ + delete d; +} + +} diff --git a/ksysguard/processcore/processes_linux_p.cpp b/ksysguard/processcore/processes_linux_p.cpp new file mode 100644 index 000000000..1fd6a100b --- /dev/null +++ b/ksysguard/processcore/processes_linux_p.cpp @@ -0,0 +1,517 @@ +/* This file is part of the KDE project + + Copyright (C) 2007 John Tapsell + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This 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 "processes_local_p.h" +#include "process.h" + +#include + +#include +#include +#include +#include +#include + +//for sysconf +#include +//for kill and setNice +#include +#include +#include +#include +#include +//for ionice +#include +#include +//for getsched +#include + +#define PROCESS_BUFFER_SIZE 1000 + +/* For ionice */ +extern int sys_ioprio_set(int, int, int); +extern int sys_ioprio_get(int, int); + +#define HAVE_IONICE +/* Check if this system has ionice */ +#if !defined(SYS_ioprio_get) || !defined(SYS_ioprio_set) +/* All new kernels have SYS_ioprio_get and _set defined, but for the few that do not, here are the definitions */ +#if defined(__i386__) +#define __NR_ioprio_set 289 +#define __NR_ioprio_get 290 +#elif defined(__ppc__) || defined(__powerpc__) +#define __NR_ioprio_set 273 +#define __NR_ioprio_get 274 +#elif defined(__x86_64__) +#define __NR_ioprio_set 251 +#define __NR_ioprio_get 252 +#elif defined(__ia64__) +#define __NR_ioprio_set 1274 +#define __NR_ioprio_get 1275 +#else +#ifdef __GNUC__ +#warning "This architecture does not support IONICE. Disabling ionice feature." +#endif +#undef HAVE_IONICE +#endif +/* Map these to SYS_ioprio_get */ +#define SYS_ioprio_get __NR_ioprio_get +#define SYS_ioprio_set __NR_ioprio_set + +#endif /* !SYS_ioprio_get */ + +/* Set up ionice functions */ +#ifdef HAVE_IONICE +#define IOPRIO_WHO_PROCESS 1 +#define IOPRIO_CLASS_SHIFT 13 + +/* Expose the kernel calls to usespace via syscall + * See man ioprio_set and man ioprio_get for information on these functions */ +static int ioprio_set(int which, int who, int ioprio) +{ + return syscall(SYS_ioprio_set, which, who, ioprio); +} + +static int ioprio_get(int which, int who) +{ + return syscall(SYS_ioprio_get, which, who); +} +#endif + + + + +namespace KSysGuard +{ + + class ProcessesLocal::Private + { + public: + Private() { mProcDir = opendir( "/proc" );} + ~Private(); + inline bool readProcStatus(long pid, Process *process); + inline bool readProcStat(long pid, Process *process); + inline bool readProcStatm(long pid, Process *process); + inline bool readProcCmdline(long pid, Process *process); + inline bool getNiceness(long pid, Process *process); + QFile mFile; + char mBuffer[PROCESS_BUFFER_SIZE+1]; //used as a buffer to read data into + DIR* mProcDir; + }; + +ProcessesLocal::Private::~Private() +{ + closedir(mProcDir); +} + +ProcessesLocal::ProcessesLocal() : d(new Private()) +{ + +} + +bool ProcessesLocal::Private::readProcStatus(long pid, Process *process) +{ + mFile.setFileName(QString("/proc/%1/status").arg(pid)); + if(!mFile.open(QIODevice::ReadOnly | QIODevice::Text)) + return false; /* process has terminated in the meantime */ + + process->uid = 0; + process->gid = 0; + process->tracerpid = 0; + + int size; + int found = 0; //count how many fields we found + while( (size = mFile.readLine( mBuffer, sizeof(mBuffer))) > 0) { //-1 indicates an error + switch( mBuffer[0]) { + case 'N': + if((unsigned int)size > sizeof("Name:") && qstrncmp(mBuffer, "Name:", sizeof("Name:")-1) == 0) { + process->name = QString::fromLocal8Bit(mBuffer + sizeof("Name:")-1, size-sizeof("Name:")+1).trimmed(); + if(++found == 4) goto finish; + } + break; + case 'U': + if((unsigned int)size > sizeof("Uid:") && qstrncmp(mBuffer, "Uid:", sizeof("Uid:")-1) == 0) { + sscanf(mBuffer + sizeof("Uid:") -1, "%Ld %Ld %Ld %Ld", &process->uid, &process->euid, &process->suid, &process->fsuid ); + if(++found == 4) goto finish; + } + break; + case 'G': + if((unsigned int)size > sizeof("Gid:") && qstrncmp(mBuffer, "Gid:", sizeof("Gid:")-1) == 0) { + sscanf(mBuffer + sizeof("Gid:")-1, "%Ld %Ld %Ld %Ld", &process->gid, &process->egid, &process->sgid, &process->fsgid ); + if(++found == 4) goto finish; + } + break; + case 'T': + if((unsigned int)size > sizeof("TracerPid:") && qstrncmp(mBuffer, "TracerPid:", sizeof("TracerPid:")-1) == 0) { + process->tracerpid = atol(mBuffer + sizeof("TracerPid:")-1); + if(++found == 4) goto finish; + } + break; + default: + break; + } + } + + finish: + mFile.close(); + return true; +} + +long ProcessesLocal::getParentPid(long pid) { + Q_ASSERT(pid != 0); + d->mFile.setFileName(QString("/proc/%1/stat").arg(pid)); + if(!d->mFile.open(QIODevice::ReadOnly | QIODevice::Text)) + return 0; /* process has terminated in the meantime */ + + int size; //amount of data read in + if( (size = d->mFile.readLine( d->mBuffer, sizeof(d->mBuffer))) <= 0) { //-1 indicates nothing read + d->mFile.close(); + return 0; + } + + d->mFile.close(); + int current_word = 0; + char *word = d->mBuffer; + + while(true) { + if(word[0] == ' ' ) { + if(++current_word == 3) + break; + } else if(word[0] == 0) { + return 0; //end of data - serious problem + } + word++; + } + return atol(++word); +} + +bool ProcessesLocal::Private::readProcStat(long pid, Process *ps) +{ + QString filename = QString("/proc/%1/stat").arg(pid); + // As an optomization, if the last file read in was stat, then we already have this info in memory + if(mFile.fileName() != filename) { + mFile.setFileName(filename); + if(!mFile.open(QIODevice::ReadOnly | QIODevice::Text)) + return false; /* process has terminated in the meantime */ + if( mFile.readLine( mBuffer, sizeof(mBuffer)) <= 0) { //-1 indicates nothing read + mFile.close(); + return false; + } + mFile.close(); + } + + int current_word = 0; //count from 0 + char *word = mBuffer; + char status='\0'; + long vmSize = 0; + long vmRSS = 0; + while(current_word < 23) { + if(word[0] == ' ' ) { + ++current_word; + switch(current_word) { + case 2: //status + status=word[1]; // Look at the first letter of the status. + // We analyze this after the while loop + break; + case 6: //ttyNo + { + int ttyNo = atoi(word+1); + int major = ttyNo >> 8; + int minor = ttyNo & 0xff; + switch(major) { + case 136: + ps->setTty(QByteArray("pts/") + QByteArray::number(minor)); + break; + case 5: + ps->setTty(QByteArray("tty")); + case 4: + if(minor < 64) + ps->setTty(QByteArray("tty") + QByteArray::number(minor)); + else + ps->setTty(QByteArray("ttyS") + QByteArray::number(minor-64)); + break; + default: + ps->setTty(QByteArray()); + } + } + break; + case 13: //userTime + ps->setUserTime(atoll(word+1)); + break; + case 14: //sysTime + ps->setSysTime(atoll(word+1)); + break; + case 18: //niceLevel + ps->setNiceLevel(atoi(word+1)); /*Or should we use getPriority instead? */ + break; + case 22: //vmSize + vmSize = atol(word+1); + break; + case 23: //vmRSS + vmRSS = atol(word+1); + break; + default: + break; + } + } else if(word[0] == 0) { + return false; //end of data - serious problem + } + word++; + } + + /* There was a "(ps->vmRss+3) * sysconf(_SC_PAGESIZE)" here in the original ksysguard code. I have no idea why! After comparing it to + * meminfo and other tools, this means we report the RSS by 12 bytes differently compared to them. So I'm removing the +3 + * to be consistent. NEXT TIME COMMENT STRANGE THINGS LIKE THAT! :-) */ + ps->setVmRSS(vmRSS * sysconf(_SC_PAGESIZE) / 1024); /*convert to KiB*/ + ps->setVmSize(vmSize /= 1024); /* convert to KiB */ + + switch( status) { + case 'R': + ps->setStatus(Process::Running); + break; + case 'S': + ps->setStatus(Process::Sleeping); + break; + case 'D': + ps->setStatus(Process::DiskSleep); + break; + case 'Z': + ps->setStatus(Process::Zombie); + break; + case 'T': + ps->setStatus(Process::Stopped); + break; + case 'W': + ps->setStatus(Process::Paging); + break; + default: + ps->setStatus(Process::OtherStatus); + break; + } + return true; +} + +bool ProcessesLocal::Private::readProcStatm(long pid, Process *process) +{ + mFile.setFileName(QString("/proc/%1/statm").arg(pid)); + if(!mFile.open(QIODevice::ReadOnly | QIODevice::Text)) + return false; /* process has terminated in the meantime */ + + if( mFile.readLine( mBuffer, sizeof(mBuffer)) <= 0) { //-1 indicates nothing read + mFile.close(); + return 0; + } + mFile.close(); + + int current_word = 0; + char *word = mBuffer; + + while(true) { + if(word[0] == ' ' ) { + if(++current_word == 2) //number of pages that are shared + break; + } else if(word[0] == 0) { + return false; //end of data - serious problem + } + word++; + } + long shared = atol(word+1); + + /* we use the rss - shared to find the amount of memory just this app uses */ + process->vmURSS = process->vmRSS - (shared * sysconf(_SC_PAGESIZE) / 1024); + return true; +} + + +bool ProcessesLocal::Private::readProcCmdline(long pid, Process *process) +{ + if(!process->command.isNull()) return true; //only parse the cmdline once + mFile.setFileName(QString("/proc/%1/cmdline").arg(pid)); + if(!mFile.open(QIODevice::ReadOnly | QIODevice::Text)) + return false; /* process has terminated in the meantime */ + + QTextStream in(&mFile); + process->command = in.readAll(); + + //cmdline seperates parameters with the NULL character + process->command.replace('\0', ' '); + process->command = process->command.trimmed(); + + mFile.close(); + return true; +} + +bool ProcessesLocal::Private::getNiceness(long pid, Process *process) { + int sched = sched_getscheduler(pid); + switch(sched) { + case (SCHED_OTHER): + process->scheduler = KSysGuard::Process::Other; + break; + case (SCHED_RR): + process->scheduler = KSysGuard::Process::RoundRobin; + break; + case (SCHED_FIFO): + process->scheduler = KSysGuard::Process::Fifo; + break; +#ifdef SCHED_BATCH + case (SCHED_BATCH): + process->scheduler = KSysGuard::Process::Batch; + break; +#endif + default: + process->scheduler = KSysGuard::Process::Other; + } + if(sched == SCHED_FIFO || sched == SCHED_RR) { + struct sched_param param; + if(sched_getparam(pid, ¶m) == 0) + process->niceLevel = param.sched_priority; + else + process->niceLevel = 0; //Error getting scheduler parameters. + } + +#ifdef HAVE_IONICE + int ioprio = ioprio_get(IOPRIO_WHO_PROCESS, pid); /* Returns from 0 to 7 for the iopriority, and -1 if there's an error */ + if(ioprio == -1) { + process->ioniceLevel = -1; + process->ioPriorityClass = KSysGuard::Process::None; + return false; /* Error. Just give up. */ + } + process->ioniceLevel = ioprio & 0xff; /* Bottom few bits are the priority */ + process->ioPriorityClass = (KSysGuard::Process::IoPriorityClass)(ioprio >> IOPRIO_CLASS_SHIFT); /* Top few bits are the class */ +#else + return false; /* Do nothing, if we do not support this architecture */ +#endif + return true; +} + +bool ProcessesLocal::updateProcessInfo( long pid, Process *process) +{ + if(!d->readProcStat(pid, process)) return false; + if(!d->readProcStatus(pid, process)) return false; + if(!d->readProcStatm(pid, process)) return false; + if(!d->readProcCmdline(pid, process)) return false; + if(!d->getNiceness(pid, process)) return false; + + return true; +} + +QSet ProcessesLocal::getAllPids( ) +{ + QSet pids; + if(d->mProcDir==NULL) return pids; //There's not much we can do without /proc + struct dirent* entry; + rewinddir(d->mProcDir); + while ( ( entry = readdir( d->mProcDir ) ) ) + if ( entry->d_name[ 0 ] >= '0' && entry->d_name[ 0 ] <= '9' ) + pids.insert(atol( entry->d_name )); + return pids; +} + +bool ProcessesLocal::sendSignal(long pid, int sig) { + if ( kill( (pid_t)pid, sig ) ) { + //Kill failed + return false; + } + return true; +} + +bool ProcessesLocal::setNiceness(long pid, int priority) { + if(pid <= 0) return false; // check the parameters + if ( setpriority( PRIO_PROCESS, pid, priority ) ) { + //set niceness failed + return false; + } + return true; +} + +bool ProcessesLocal::setScheduler(long pid, int priorityClass, int priority) { + if(priorityClass == KSysGuard::Process::Other || priorityClass == KSysGuard::Process::Batch) + priority = 0; + if(pid <= 0) return false; // check the parameters + struct sched_param params; + params.sched_priority = priority; + switch(priorityClass) { + case (KSysGuard::Process::Other): + return (sched_setscheduler( pid, SCHED_OTHER, ¶ms) == 0); + case (KSysGuard::Process::RoundRobin): + return (sched_setscheduler( pid, SCHED_RR, ¶ms) == 0); + case (KSysGuard::Process::Fifo): + return (sched_setscheduler( pid, SCHED_FIFO, ¶ms) == 0); +#ifdef SCHED_BATCH + case (KSysGuard::Process::Batch): + return (sched_setscheduler( pid, SCHED_BATCH, ¶ms) == 0); +#endif + default: + return false; + } +} + + +bool ProcessesLocal::setIoNiceness(long pid, int priorityClass, int priority) { +#ifdef HAVE_IONICE + if (ioprio_set(IOPRIO_WHO_PROCESS, pid, priority | priorityClass << IOPRIO_CLASS_SHIFT) == -1) { + //set io niceness failed + return false; + } + return true; +#else + return false; +#endif +} + +bool ProcessesLocal::supportsIoNiceness() { +#ifdef HAVE_IONICE + return true; +#else + return false; +#endif +} + +long long ProcessesLocal::totalPhysicalMemory() { + //Try to get the memory via sysconf. Note the cast to long long to try to avoid a long overflow + //Should we use sysconf(_SC_PAGESIZE) or getpagesize() ? + long long memory = ((long long)sysconf(_SC_PHYS_PAGES)) * (sysconf(_SC_PAGESIZE)/1024); + if(memory > 0) return memory; + + //This is backup code incase the above failed. It should never fail on a linux system. + + d->mFile.setFileName("/proc/meminfo"); + if(!d->mFile.open(QIODevice::ReadOnly | QIODevice::Text)) + return 0; + + int size; + while( (size = d->mFile.readLine( d->mBuffer, sizeof(d->mBuffer))) > 0) { //-1 indicates an error + switch( d->mBuffer[0]) { + case 'M': + if((unsigned int)size > sizeof("MemTotal:") && qstrncmp(d->mBuffer, "MemTotal:", sizeof("MemTotal:")-1) == 0) { + d->mFile.close(); + return atoll(d->mBuffer + sizeof("MemTotal:")-1); + } + } + } + return 0; // Not found. Probably will never happen +} +ProcessesLocal::~ProcessesLocal() +{ + delete d; +} + +} diff --git a/ksysguard/processcore/processes_local_p.cpp b/ksysguard/processcore/processes_local_p.cpp new file mode 100644 index 000000000..5ab9fb579 --- /dev/null +++ b/ksysguard/processcore/processes_local_p.cpp @@ -0,0 +1,37 @@ +/* This file is part of the KDE project + + Copyright (C) 2007 John Tapsell + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This 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. + +*/ + +#if defined __linux__ +#include "processes_linux_p.cpp" +#elif defined __FreeBSD__ || defined __DragonFly__ +#include "processes_freebsd_p.cpp" +#elif defined __OpenBSD__ +#include "processes_openbsd_p.cpp" +#elif defined __NetBSD__ +#include "processes_netbsd_p.cpp" +#else +// Use Qt's OS detection +#include +#ifdef Q_OS_SOLARIS +#include "processes_solaris_p.cpp" +#endif +#endif + diff --git a/ksysguard/processcore/processes_local_p.h b/ksysguard/processcore/processes_local_p.h new file mode 100644 index 000000000..202f4bf7d --- /dev/null +++ b/ksysguard/processcore/processes_local_p.h @@ -0,0 +1,70 @@ +/* This file is part of the KDE project + + Copyright (C) 2007 John Tapsell + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This 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 PROCESSES_LOCAL_H_ +#define PROCESSES_LOCAL_H_ + +#include "processes_base_p.h" +#include //For sysconf + + +#include + +namespace KSysGuard +{ + class Process; + + /** + * This is the OS specific code to get process information for the local host. + */ + class ProcessesLocal : public AbstractProcesses { + public: + ProcessesLocal(); + virtual ~ProcessesLocal(); + virtual QSet getAllPids(); + virtual long getParentPid(long pid); + virtual bool updateProcessInfo(long pid, Process *process); + virtual bool sendSignal(long pid, int sig); + virtual bool setNiceness(long pid, int priority); + virtual bool setScheduler(long pid, int priorityClass, int priority); + virtual long long totalPhysicalMemory(); + virtual bool setIoNiceness(long pid, int priorityClass, int priority); + virtual bool supportsIoNiceness(); + virtual long numberProcessorCores() +#ifdef _SC_NPROCESSORS_ONLN + { return sysconf(_SC_NPROCESSORS_ONLN); } // Should work on any recent posix system +#else + ; +#endif + virtual void updateAllProcesses() { emit processesUpdated(); } //For local machine, there is no delay + + private: + /** + * You can use this for whatever data you want. Be careful about preserving state in between getParentPid and updateProcessInfo calls + * if you chose to do that. getParentPid may be called several times for different pids before the relevant updateProcessInfo calls are made. + * This is because the tree structure has to be sorted out first. + */ + class Private; + Private *d; + + }; +} +#endif diff --git a/ksysguard/processcore/processes_netbsd_p.cpp b/ksysguard/processcore/processes_netbsd_p.cpp new file mode 100644 index 000000000..7996f0337 --- /dev/null +++ b/ksysguard/processcore/processes_netbsd_p.cpp @@ -0,0 +1,292 @@ +/* This file is part of the KDE project + Copyright (C) 2007 Manolo Valdes + Copyright (C) 2007 Mark Davies + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This 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 "processes_local_p.h" +#include "process.h" + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + + +namespace KSysGuard +{ + + class ProcessesLocal::Private + { + public: + Private() { kd = kvm_open(NULL, NULL, NULL, KVM_NO_FILES, "kvm_open");} + ~Private() { kvm_close(kd);} + inline bool readProc(long pid, struct kinfo_proc2 **p, int *num); + inline void readProcStatus(struct kinfo_proc2 *p, Process *process); + inline void readProcStat(struct kinfo_proc2 *p, Process *process); + inline void readProcStatm(struct kinfo_proc2 *p, Process *process); + inline bool readProcCmdline(struct kinfo_proc2 *p, Process *process); + + kvm_t *kd; + }; + +#ifndef _SC_NPROCESSORS_ONLN +long int KSysGuard::ProcessesLocal::numberProcessorCores() +{ + int mib[2]; + int ncpu; + size_t len; + + mib[0] = CTL_HW; + mib[1] = HW_NCPU; + len = sizeof(ncpu); + + if (sysctl(mib, 2, &ncpu, &len, NULL, 0) == -1 || !len) + return 1; + return len; +} +#endif + +bool ProcessesLocal::Private::readProc(long pid, struct kinfo_proc2 **p, int *num) +{ + int len; + int op, arg; + + if (pid == 0) { + op = KERN_PROC_ALL; + arg = 0; + } else { + op = KERN_PROC_PID; + arg = pid; + } + *p = kvm_getproc2(kd, op, arg, sizeof(struct kinfo_proc2), &len); + + if (len < 1) + return false; + + if (num != NULL) + *num = len; + return true; +} + +void ProcessesLocal::Private::readProcStatus(struct kinfo_proc2 *p, Process *process) +{ + process->setUid(p->p_ruid); + process->setEuid(p->p_uid); + process->setGid(p->p_rgid); + process->setEgid(p->p_gid); + process->setTracerpid(0); + + process->setName(QString(p->p_comm ? p->p_comm : "????")); +} + +void ProcessesLocal::Private::readProcStat(struct kinfo_proc2 *p, Process *ps) +{ + const char *ttname; + dev_t dev; + + ps->setUserTime(p->p_uutime_sec*100+p->p_uutime_usec/10000); + ps->setSysTime(p->p_ustime_sec*100+p->p_ustime_usec/10000); + + ps->setUserUsage(100.0 * ((double)(p->p_pctcpu) / FSCALE)); + ps->setSysUsage(0); + + ps->setNiceLevel(p->p_nice - NZERO); + ps->setVmSize((p->p_vm_tsize + p->p_vm_dsize + p->p_vm_ssize) + * getpagesize()); + ps->setVmRSS(p->p_vm_rssize * getpagesize()); + +// "idle","run","sleep","stop","zombie" + switch( p->p_stat ) { + case LSRUN: + ps->setStatus(Process::Running); + break; + case LSSLEEP: + ps->setStatus(Process::Sleeping); + break; + case LSSTOP: + ps->setStatus(Process::Stopped); + break; + case LSZOMB: + ps->setStatus(Process::Zombie); + break; + case LSONPROC: + ps->setStatus(Process::Running); + break; + default: + ps->setStatus(Process::OtherStatus); + break; + } + + dev = p->p_tdev; + if (dev == NODEV || (ttname = devname(dev, S_IFCHR)) == NULL) { + ps->setTty(QByteArray()); + } else { + ps->setTty(QByteArray(ttname)); + } +} + +void ProcessesLocal::Private::readProcStatm(struct kinfo_proc2 *p, Process *process) +{ +// TODO + +// unsigned long shared; +// process->vmURSS = process->vmRSS - (shared * sysconf(_SC_PAGESIZE) / 1024); + process->setVmURSS(-1); +} + +bool ProcessesLocal::Private::readProcCmdline(struct kinfo_proc2 *p, Process *process) +{ + char **argv; + + if ((argv = kvm_getargv2(kd, p, 256)) == NULL) + return false; + + QString command = QString(""); + + while (*argv) { + command += *argv; + command += " "; + argv++; + } + process->setCommand(command.trimmed()); + + return true; +} + +ProcessesLocal::ProcessesLocal() : d(new Private()) +{ + +} + +long ProcessesLocal::getParentPid(long pid) { + long long ppid = 0; + struct kinfo_proc2 *p; + if(d->readProc(pid, &p, 0)) + { + ppid = p->p_ppid; + } + return ppid; +} + +bool ProcessesLocal::updateProcessInfo( long pid, Process *process) +{ + struct kinfo_proc2 *p; + if(!d->readProc(pid, &p, NULL)) return false; + d->readProcStat(p, process); + d->readProcStatus(p, process); + d->readProcStatm(p, process); + if(!d->readProcCmdline(p, process)) return false; + + return true; +} + +QSet ProcessesLocal::getAllPids( ) +{ + QSet pids; + int len; + int num; + struct kinfo_proc2 *p; + + d->readProc(0, &p, &len); + + for (num = 0; num < len; num++) + { + long pid = p[num].p_pid; + long long ppid = p[num].p_ppid; + + //skip all process with parent id = 0 but init + if(ppid == 0 && pid != 1) + continue; + pids.insert(pid); + } + return pids; +} + +bool ProcessesLocal::sendSignal(long pid, int sig) { + if ( kill( (pid_t)pid, sig ) ) { + //Kill failed + return false; + } + return true; +} + +bool ProcessesLocal::setNiceness(long pid, int priority) { + if ( setpriority( PRIO_PROCESS, pid, priority ) ) { + //set niceness failed + return false; + } + return true; +} + +bool ProcessesLocal::setScheduler(long pid, int priorityClass, int priority) +{ + if(priorityClass == KSysGuard::Process::Other || priorityClass == KSysGuard::Process::Batch) + priority = 0; + if(pid <= 0) return false; // check the parameters + struct sched_param params; + params.sched_priority = priority; + switch(priorityClass) { + case (KSysGuard::Process::Other): + return (sched_setscheduler( pid, SCHED_OTHER, ¶ms) == 0); + case (KSysGuard::Process::RoundRobin): + return (sched_setscheduler( pid, SCHED_RR, ¶ms) == 0); + case (KSysGuard::Process::Fifo): + return (sched_setscheduler( pid, SCHED_FIFO, ¶ms) == 0); +#ifdef SCHED_BATCH + case (KSysGuard::Process::Batch): + return (sched_setscheduler( pid, SCHED_BATCH, ¶ms) == 0); +#endif + default: + return false; + } +} + +bool ProcessesLocal::setIoNiceness(long pid, int priorityClass, int priority) { + return false; //Not yet supported +} + +bool ProcessesLocal::supportsIoNiceness() { + return false; +} + +long long ProcessesLocal::totalPhysicalMemory() { + + size_t Total; + size_t len; + len = sizeof (Total); + sysctlbyname("hw.physmem", &Total, &len, NULL, 0); + return Total /= 1024; +} + +ProcessesLocal::~ProcessesLocal() +{ + delete d; +} + +} diff --git a/ksysguard/processcore/processes_openbsd_p.cpp b/ksysguard/processcore/processes_openbsd_p.cpp new file mode 100644 index 000000000..87e55fa52 --- /dev/null +++ b/ksysguard/processcore/processes_openbsd_p.cpp @@ -0,0 +1,306 @@ +/* This file is part of the KDE project + Copyright (C) 2007 Manolo Valdes + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This 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 "processes_local_p.h" +#include "process.h" + +#include + +#include + +#include +#include +#include +#include +#include +#if defined(__DragonFly__) +#include +#include +#endif +#include +#include +#include + + + + +namespace KSysGuard +{ + + class ProcessesLocal::Private + { + public: + Private() {;} + ~Private() {;} + inline bool readProc(long pid, struct kinfo_proc *p); + inline void readProcStatus(struct kinfo_proc *p, Process *process); + inline void readProcStat(struct kinfo_proc *p, Process *process); + inline void readProcStatm(struct kinfo_proc *p, Process *process); + inline bool readProcCmdline(long pid, Process *process); + }; + +bool ProcessesLocal::Private::readProc(long pid, struct kinfo_proc *p) +{ + int mib[4]; + size_t len; + + mib[0] = CTL_KERN; + mib[1] = KERN_PROC; + mib[2] = KERN_PROC_PID; + mib[3] = pid; + + len = sizeof (struct kinfo_proc); + if (sysctl(mib, 4, p, &len, NULL, 0) == -1 || !len) + return false; + return true; +} + +void ProcessesLocal::Private::readProcStatus(struct kinfo_proc *p, Process *process) +{ + process->setUid(0); + process->setGid(0); + process->setTracerpid(0); + + +#if defined(__FreeBSD__) && __FreeBSD_version >= 500015 + process->setUid(p->ki_uid); + process->setGid(p->ki_pgid); + process->setName(QString(p->ki_comm ? p->ki_comm : "????")); +#elif defined(__DragonFly__) && __DragonFly_version >= 190000 + process->setUid(p->kp_uid); + process->setGid(p->kp_pgid); + process->setName(QString(p->kp_comm ? p->kp_comm : "????")); +#else + process->setUid(p->kp_eproc.e_ucred.cr_uid); + process->setGid(p->kp_eproc.e_pgid); +#endif +} + +void ProcessesLocal::Private::readProcStat(struct kinfo_proc *p, Process *ps) +{ + int status; + struct rusage pru; +#if defined(__FreeBSD__) && __FreeBSD_version >= 500015 + ps->setUserTime(p->ki_runtime / 10000); + ps->setNiceLevel(p->ki_nice); + ps->setVmSize(p->ki_size); + ps->setVmRSS(p->ki_rssize * getpagesize()); + status = p->ki_stat; +#elif defined(__DragonFly__) && __DragonFly_version >= 190000 + if (!getrusage(p->kp_pid, &pru)) { + errx(1, "failed to get rusage info"); + } + ps->setUserTime(pru.ru_utime.tv_usec / 1000); /*p_runtime / 1000*/ + ps->setNiceLevel(p->kp_nice); + ps->setVmSize(p->kp_vm_map_size); + ps->setVmRSS(p->kp_vm_rssize * getpagesize()); + status = p->kp_stat; +#else + ps->setUserTime(p->kp_proc.p_rtime.tv_sec*100+p->kp_proc.p_rtime.tv_usec/100); + ps->setNiceLevel(p->kp_proc.p_nice); + ps->setVmSize(p->kp_eproc.e_vm.vm_map.size); + ps->setVmRSS(p->kp_eproc.e_vm.vm_rssize * getpagesize()); + status = p->kp_proc.p_stat; +#endif + ps->setSysTime(0); + +// "idle","run","sleep","stop","zombie" + switch( status ) { + case '0': + ps->setStatus(Process::DiskSleep); + break; + case '1': + ps->setStatus(Process::Running); + break; + case '2': + ps->setStatus(Process::Sleeping); + break; + case '3': + ps->setStatus(Process::Stopped); + break; + case '4': + ps->setStatus(Process::Zombie); + break; + default: + ps->setStatus(Process::OtherStatus); + break; + } +} + +void ProcessesLocal::Private::readProcStatm(struct kinfo_proc *p, Process *process) +{ +// TODO + +// unsigned long shared; +// process->setVmURSS(process->vmRSS - (shared * sysconf(_SC_PAGESIZE) / 1024)); +} + +bool ProcessesLocal::Private::readProcCmdline(long pid, Process *process) +{ + int mib[4]; + struct kinfo_proc p; + size_t buflen = 256; + char buf[256]; + + mib[0] = CTL_KERN; + mib[1] = KERN_PROC; + mib[2] = KERN_PROC_ARGS; + mib[3] = pid; + + if (sysctl(mib, 4, buf, &buflen, NULL, 0) == -1 || !buflen) + return false; + QString command = QString(buf); + + //cmdline seperates parameters with the NULL character + command.replace('\0', ' '); + process->setCommand(command.trimmed()); + + return true; +} + +ProcessesLocal::ProcessesLocal() : d(new Private()) +{ + +} + +long ProcessesLocal::getParentPid(long pid) { + Q_ASSERT(pid != 0); + long long ppid = 0; + struct kinfo_proc p; + if(d->readProc(pid, &p)) + { +#if defined(__FreeBSD__) && __FreeBSD_version >= 500015 + ppid = p.ki_ppid; +#elif defined(__DragonFly__) && __DragonFly_version >= 190000 + ppid = p.kp_ppid; +#else + ppid = p.kp_eproc.e_ppid; +#endif + } + return ppid; +} + +bool ProcessesLocal::updateProcessInfo( long pid, Process *process) +{ + struct kinfo_proc p; + if(!d->readProc(pid, &p)) return false; + d->readProcStat(&p, process); + d->readProcStatus(&p, process); + d->readProcStatm(&p, process); + if(!d->readProcCmdline(pid, process)) return false; + + return true; +} + +QSet ProcessesLocal::getAllPids( ) +{ + QSet pids; + int mib[3]; + size_t len; + size_t num; + struct kinfo_proc *p; + + mib[0] = CTL_KERN; + mib[1] = KERN_PROC; + mib[2] = KERN_PROC_ALL; + sysctl(mib, 3, NULL, &len, NULL, 0); + p = (kinfo_proc *) malloc(len); + sysctl(mib, 3, p, &len, NULL, 0); + + for (num = 0; num < len / sizeof(struct kinfo_proc); num++) +#if defined(__FreeBSD__) && __FreeBSD_version >= 500015 + pids.insert(p[num].ki_pid); +#elif defined(__DragonFly__) && __DragonFly_version >= 190000 + pids.insert(p[num].kp_pid); +#else + pids.insert(p[num].kp_proc.p_pid); +#endif + free(p); + return pids; +} + +bool ProcessesLocal::sendSignal(long pid, int sig) { + if ( kill( (pid_t)pid, sig ) ) { + //Kill failed + return false; + } + return true; +} + +bool ProcessesLocal::setNiceness(long pid, int priority) { + if ( setpriority( PRIO_PROCESS, pid, priority ) ) { + //set niceness failed + return false; + } + return true; +} + +bool ProcessesLocal::setScheduler(long pid, int priorityClass, int priority) +{ + if(priorityClass == KSysGuard::Process::Other || priorityClass == KSysGuard::Process::Batch) + priority = 0; + if(pid <= 0) return false; // check the parameters + return false; +} + +bool ProcessesLocal::setIoNiceness(long pid, int priorityClass, int priority) { + return false; //Not yet supported +} + +bool ProcessesLocal::supportsIoNiceness() { + return false; +} + +long long ProcessesLocal::totalPhysicalMemory() { + + static int physmem_mib[] = { CTL_HW, HW_PHYSMEM }; + /* get the page size with "getpagesize" and calculate pageshift from + * it */ + int pagesize = ::getpagesize(); + int pageshift = 0; + while (pagesize > 1) { + pageshift++; + pagesize >>= 1; + } + size_t Total = 0; + size_t size = sizeof(Total); + sysctl(physmem_mib, 2, &Total, &size, NULL, 0); + return Total /= 1024; +} + +long int KSysGuard::ProcessesLocal::numberProcessorCores() +{ + int mib[2]; + int ncpu; + size_t len; + + mib[0] = CTL_HW; + mib[1] = HW_NCPU; + len = sizeof(ncpu); + + if (sysctl(mib, 2, &ncpu, &len, NULL, 0) == -1 || !len) + return 1; + return len; +} +ProcessesLocal::~ProcessesLocal() +{ + delete d; +} + +} diff --git a/ksysguard/processcore/processes_remote_p.cpp b/ksysguard/processcore/processes_remote_p.cpp new file mode 100644 index 000000000..eb5e096a5 --- /dev/null +++ b/ksysguard/processcore/processes_remote_p.cpp @@ -0,0 +1,267 @@ +/* This file is part of the KDE project + + Copyright (C) 2007 John Tapsell + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This 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 "processes_remote_p.h" +#include "process.h" + +#include +#include +#include + +#include +#include + + + + + +namespace KSysGuard +{ + + class ProcessesRemote::Private + { + public: + Private() {havePsInfo = false; pidColumn = 1; + ppidColumn = nameColumn = uidColumn = gidColumn = + statusColumn = userColumn = systemColumn = niceColumn = + vmSizeColumn = vmRSSColumn = loginColumn = commandColumn = + tracerPidColumn = ttyColumn = ioprioClassColumn = ioprioColumn = + vmURSSColumn = -1; + usedMemory = freeMemory;} + ~Private() {;} + QString host; + QList lastAnswer; + QSet pids; + QHash > processByPid; + + bool havePsInfo; + int pidColumn; + int ppidColumn; + int tracerPidColumn; + int nameColumn; + int uidColumn; + int gidColumn; + int statusColumn; + int userColumn; + int systemColumn; + int niceColumn; + int vmSizeColumn; + int vmRSSColumn; + int vmURSSColumn; + int loginColumn; + int commandColumn; + int ioprioClassColumn; + int ioprioColumn; + int ttyColumn; + + int numColumns; + + long freeMemory; + long usedMemory; + + }; +ProcessesRemote::ProcessesRemote(const QString &hostname) : d(new Private()) +{ + d->host = hostname; + QTimer::singleShot(0, this, SLOT(setup())); +} + +void ProcessesRemote::setup() { + emit runCommand("mem/physical/used", (int)UsedMemory); + emit runCommand("mem/physical/free", (int)FreeMemory); + emit runCommand("ps?", (int)PsInfo); + emit runCommand("ps", (int)Ps); +} + + +long ProcessesRemote::getParentPid(long pid) { + if(!d->processByPid.contains(pid)) { + kDebug() << "Parent pid requested for pid that we do not have info on " << pid; + return 0; + } + if(d->ppidColumn == -1) { + kDebug() << "ppid column not known "; + return 0; + } + return d->processByPid[pid].at(d->ppidColumn).toLong(); +} +bool ProcessesRemote::updateProcessInfo( long pid, Process *process) +{ + Q_CHECK_PTR(process); + if(!d->processByPid.contains(pid)) { + kDebug() << "update request for pid that we do not have info on " << pid; + return false; + } + QList p = d->processByPid[pid]; + + if(d->nameColumn!= -1) process->setName(p.at(d->nameColumn)); + if(d->uidColumn!= -1) process->setUid(p.at(d->uidColumn).toLong()); + if(d->gidColumn!= -1) process->setGid(p.at(d->gidColumn).toLong()); + if(d->statusColumn!= -1) { + switch( p.at(d->statusColumn)[0] ) { + case 's': + process->setStatus(Process::Sleeping); + break; + case 'r': + process->setStatus(Process::Running); + break; + } + } + if(d->userColumn!= -1) process->setUserTime(p.at(d->userColumn).toLong()); + if(d->systemColumn!= -1) process->setSysTime(p.at(d->systemColumn).toLong()); + if(d->niceColumn!= -1) process->setNiceLevel(p.at(d->niceColumn).toLong()); + if(d->vmSizeColumn!= -1) process->setVmSize(p.at(d->vmSizeColumn).toLong()); + if(d->vmRSSColumn!= -1) process->setVmRSS(p.at(d->vmRSSColumn).toLong()); + if(d->vmURSSColumn!= -1) process->setVmURSS(p.at(d->vmURSSColumn).toLong()); + if(d->loginColumn!= -1) process->setLogin(QString::fromUtf8(p.at(d->loginColumn).data())); + if(d->commandColumn!= -1) process->setCommand(QString::fromUtf8(p.at(d->commandColumn).data())); + if(d->tracerPidColumn!= -1) process->setTracerpid(p.at(d->tracerPidColumn).toLong()); + if(d->vmURSSColumn!= -1) process->setVmURSS(p.at(d->vmURSSColumn).toLong()); + if(d->ttyColumn!= -1) process->setTty(p.at(d->ttyColumn)); + if(d->ioprioColumn!= -1) process->setIoniceLevel(p.at(d->ioprioColumn).toInt()); + if(d->ioprioClassColumn!= -1) process->setIoPriorityClass((KSysGuard::Process::IoPriorityClass)(p.at(d->ioprioClassColumn).toInt())); + + return true; +} + +void ProcessesRemote::updateAllProcesses() +{ + if(!d->havePsInfo) + emit runCommand("ps?", (int)PsInfo); + emit runCommand("ps", (int)Ps); +} +QSet ProcessesRemote::getAllPids( ) +{ + d->pids.clear(); + d->processByPid.clear(); + foreach(const QByteArray &process, d->lastAnswer) { + QList info = process.split('\t'); + if(info.size() == d->numColumns) { + int pid = info.at(d->pidColumn).toLong(); + Q_ASSERT(! d->pids.contains(pid)); + d->pids << pid; + d->processByPid[pid] = info; + } + } + return d->pids; +} + +bool ProcessesRemote::sendSignal(long pid, int sig) { + //TODO run the proper command for all these functions below + emit runCommand("kill " + QString::number(pid) + " " + QString::number(sig), (int)Kill); + return true; +} +bool ProcessesRemote::setNiceness(long pid, int priority) { + emit runCommand("setpriority " + QString::number(pid) + " " + QString::number(priority), (int)Renice); + return true; +} + +bool ProcessesRemote::setIoNiceness(long pid, int priorityClass, int priority) { + emit runCommand("ionice " + QString::number(pid) + " " + QString::number(priorityClass) + " " + QString::number(priority), (int)Ionice); + return true; +} + +bool ProcessesRemote::setScheduler(long pid, int priorityClass, int priority) { + return false; +} + +bool ProcessesRemote::supportsIoNiceness() { + return true; +} + +long long ProcessesRemote::totalPhysicalMemory() { + return d->usedMemory + d->freeMemory; +} +long ProcessesRemote::numberProcessorCores() { + return 0; +} + +void ProcessesRemote::answerReceived( int id, const QList& answer ) { + switch (id) { + case PsInfo: { + if(answer.isEmpty()) return; //Invalid data + QList info = answer.at(0).split('\t'); + d->numColumns = info.size(); + for(int i =0; i < d->numColumns; i++) { + if(info[i] == "Name") + d->nameColumn = i; + else if(info[i] == "PID") + d->pidColumn = i; + else if(info[i] == "PPID") + d->ppidColumn = i; + else if(info[i] == "UID") + d->uidColumn = i; + else if(info[i] == "GID") + d->gidColumn = i; + else if(info[i] == "TracerPID") + d->tracerPidColumn = i; + else if(info[i] == "Status") + d->statusColumn = i; + else if(info[i] == "User Time") + d->userColumn = i; + else if(info[i] == "System Time") + d->systemColumn = i; + else if(info[i] == "Nice") + d->niceColumn = i; + else if(info[i] == "VmSize") + d->vmSizeColumn = i; + else if(info[i] == "VmRss") + d->vmRSSColumn = i; + else if(info[i] == "VmURss") + d->vmURSSColumn = i; + else if(info[i] == "Login") + d->loginColumn = i; + else if(info[i] == "TTY") + d->ttyColumn = i; + else if(info[i] == "Command") + d->commandColumn = i; + else if(info[i] == "IO Priority Class") + d->ioprioClassColumn = i; + else if(info[i] == "IO Priority") + d->ioprioColumn = i; + } + d->havePsInfo = true; + break; + } + case Ps: + d->lastAnswer = answer; + if(!d->havePsInfo) return; //Not setup yet. Should never happen + emit processesUpdated(); + case FreeMemory: + if(answer.isEmpty()) return; //Invalid data + d->freeMemory = answer[0].toLong(); + break; + case UsedMemory: + if(answer.isEmpty()) return; //Invalid data + d->usedMemory = answer[0].toLong(); + break; + } + +} + +ProcessesRemote::~ProcessesRemote() +{ + delete d; +} + +} + +#include "processes_remote_p.moc" + diff --git a/ksysguard/processcore/processes_remote_p.h b/ksysguard/processcore/processes_remote_p.h new file mode 100644 index 000000000..40ac620ed --- /dev/null +++ b/ksysguard/processcore/processes_remote_p.h @@ -0,0 +1,78 @@ +/* This file is part of the KDE project + + Copyright (C) 2007 John Tapsell + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This 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 PROCESSES_REMOTE_P_H_ +#define PROCESSES_REMOTE_P_H_ + +#include "processes_base_p.h" +#include +class Process; +namespace KSysGuard +{ + /** + * This is used to connect to a remote host + */ + class ProcessesRemote : public AbstractProcesses { + Q_OBJECT + public: + ProcessesRemote(const QString &hostname); + virtual ~ProcessesRemote(); + virtual QSet getAllPids(); + virtual long getParentPid(long pid); + virtual bool updateProcessInfo(long pid, Process *process); + virtual bool sendSignal(long pid, int sig); + virtual bool setNiceness(long pid, int priority); + virtual bool setScheduler(long pid, int priorityClass, int priority); + virtual long long totalPhysicalMemory(); + virtual bool setIoNiceness(long pid, int priorityClass, int priority); + virtual bool supportsIoNiceness(); + virtual long numberProcessorCores(); + virtual void updateAllProcesses(); + + + Q_SIGNALS: + /** For a remote machine, we rely on being able to communicate with ksysguardd. + * This must be dealt with by the program including this widget. It must listen to our + * 'runCommand' signal, and run the given command, with the given id. */ + void runCommand(const QString &command, int id); + + public Q_SLOTS: + /** For a remote machine, we rely on being able to communicate with ksysguardd. + * The programming using this must call this slot when an answer is received from ksysguardd, + * in response to a runCommand request. The id identifies the answer */ + void answerReceived( int id, const QList& answer ); + /** Called soon after */ + void setup(); + + protected: + enum { PsInfo, Ps, UsedMemory, FreeMemory, Kill, Renice, Ionice }; + + private: + /** + * You can use this for whatever data you want. Be careful about preserving state in between getParentPid and updateProcessInfo calls + * if you chose to do that. getParentPid may be called several times for different pids before the relevant updateProcessInfo calls are made. + * This is because the tree structure has to be sorted out first. + */ + class Private; + Private *d; + + }; +} +#endif diff --git a/ksysguard/processcore/processes_solaris_p.cpp b/ksysguard/processcore/processes_solaris_p.cpp new file mode 100644 index 000000000..c3b0566a3 --- /dev/null +++ b/ksysguard/processcore/processes_solaris_p.cpp @@ -0,0 +1,100 @@ +/* This file is part of the KDE project + Copyright (C) 2007 Adriaan de Groot + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This 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 "processes_local_p.h" +#include "process.h" + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __GNUC__ +#warning Totally bogus ProcessesLocal implementation +#endif + +namespace KSysGuard +{ + +class ProcessesLocal::Private +{ +public: + Private() { }; + ~Private() { }; +} ; + +ProcessesLocal::ProcessesLocal() : d(0) +{ +} + +long ProcessesLocal::getParentPid(long pid) { + long long ppid = 0; + return ppid; +} + +bool ProcessesLocal::updateProcessInfo( long pid, Process *process) +{ + return false; +} + +QSet ProcessesLocal::getAllPids( ) +{ + QSet pids; + return pids; +} + +bool ProcessesLocal::sendSignal(long pid, int sig) { + return false; +} + +bool ProcessesLocal::setNiceness(long pid, int priority) { + return false; +} + +bool ProcessesLocal::setScheduler(long pid, int priorityClass, int priority) +{ + return false; +} + +bool ProcessesLocal::setIoNiceness(long pid, int priorityClass, int priority) { + return false; //Not yet supported +} + +bool ProcessesLocal::supportsIoNiceness() { + return false; +} + +long long ProcessesLocal::totalPhysicalMemory() { + return 0; +} + +ProcessesLocal::~ProcessesLocal() +{ + delete d; +} + +} diff --git a/ksysguard/processui/CMakeLists.txt b/ksysguard/processui/CMakeLists.txt new file mode 100644 index 000000000..3e66ec1db --- /dev/null +++ b/ksysguard/processui/CMakeLists.txt @@ -0,0 +1,91 @@ + +include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/../ ../processcore/) + +check_include_files(sys/ptrace.h HAVE_SYS_PTRACE_H) +check_include_files(sys/endian.h HAVE_SYS_ENDIAN_H) +check_include_files(byteswap.h HAVE_BYTESWAP_H) + +if (HAVE_SYS_PTRACE_H) + set(_SUPPORTED_REGS_STRUCT_CHECK " + #include + #include + + #if defined(__i386__) + # define _regs_struct user_regs_struct + # define REG_ORIG_ACCUM orig_eax + #elif defined( __amd64__) + # define _regs_struct user_regs_struct + # define REG_ORIG_ACCUM orig_rax + #elif defined(__ppc__) || defined(__powerpc__) || defined(__powerpc64__) || defined(__PPC__) || defined(powerpc) + # define _regs_struct pt_regs; + # define REG_ORIG_ACCUM gpr[0] + #endif + + int main() { + struct _regs_struct* regs; + return regs->REG_ORIG_ACCUM == SYS_fork; + }") + + include(CheckCSourceCompiles) + check_c_source_compiles("${_SUPPORTED_REGS_STRUCT_CHECK}" HAVE_KSYSGUARD_SUPPORTED_REGS_STRUCT) +else (HAVE_SYS_PTRACE_H) + # Even if we don't have ptrace, we need KMonitorProcessIO.cpp + # because the widget is referenced from the .widgets file and + # from the .ui files. + set(HAVE_KSYSGUARD_SUPPORTED_REGS_STRUCT "NO") +endif (HAVE_SYS_PTRACE_H) + +if (HAVE_KSYSGUARD_SUPPORTED_REGS_STRUCT) + add_definitions(-DWITH_MONITOR_PROCESS_IO) + set(processui_ptrace_SRCS KMonitorProcessIO.cpp DisplayProcessDlg.cpp) + set(ksysguard_WIDGETS "${CMAKE_CURRENT_BINARY_DIR}/ksysguard.generated_widgets") + + # Merge both widget files + file(READ ksysguard.widgets _ksysguard_buffer) + file(WRITE ${ksysguard_WIDGETS} "${_ksysguard_buffer}") + file(READ KMonitorProcessIO.widgets _ksysguard_buffer) + file(APPEND ${ksysguard_WIDGETS} "${_ksysguard_buffer}") +else (HAVE_KSYSGUARD_SUPPORTED_REGS_STRUCT) + set(processui_ptrace_SRCS ) + set(ksysguard_WIDGETS "ksysguard.widgets") +endif (HAVE_KSYSGUARD_SUPPORTED_REGS_STRUCT) + +set(processui_LIB_SRCS + ksysguardprocesslist.cpp + ProcessFilter.cc + ProcessModel.cc + ReniceDlg.cc + KTextEditVT.cpp + ${processui_ptrace_SRCS} +) + +kde4_add_ui_files( processui_LIB_SRCS + ReniceDlgUi.ui + ProcessWidgetUI.ui + DisplayProcessUi.ui +) + + +kde4_add_library(processui SHARED ${processui_LIB_SRCS}) + +target_link_libraries(processui ${KDE4_KDEUI_LIBS} processcore) + +set_target_properties(processui + PROPERTIES VERSION ${GENERIC_LIB_VERSION} + SOVERSION ${GENERIC_LIB_SOVERSION} + ${KDE4_DISABLE_PROPERTY_}LINK_INTERFACE_LIBRARIES "${KDE4_KDEUI_LIBS};processcore" + ) + +install(TARGETS processui ${INSTALL_TARGETS_DEFAULT_ARGS} ) + +#---------------------- + +KDE4_ADD_WIDGET_FILES(ksysguardwidgets_PART_SRCS ${ksysguard_WIDGETS}) + +kde4_add_plugin(ksysguardwidgets ${ksysguardwidgets_PART_SRCS}) + +target_link_libraries(ksysguardwidgets ${KDE4_KDEUI_LIBS} processui) + +install(TARGETS ksysguardwidgets DESTINATION ${PLUGIN_INSTALL_DIR}/plugins/designer ) + +install( FILES ProcessModel.h DisplayProcessDlg.h ProcessFilter.h KTextEditVT.h ksysguardprocesslist.h DESTINATION ${INCLUDE_INSTALL_DIR}/ksysguard COMPONENT Devel) diff --git a/ksysguard/processui/DisplayProcessDlg.cpp b/ksysguard/processui/DisplayProcessDlg.cpp new file mode 100644 index 000000000..7239ed962 --- /dev/null +++ b/ksysguard/processui/DisplayProcessDlg.cpp @@ -0,0 +1,100 @@ +/* + KSysGuard, the KDE System Guard + + Copyright (C) 2007 Trent Waddington + Copyright (c) 2008 John Tapsell + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This 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 "KMonitorProcessIO.h" +#include "DisplayProcessDlg.h" +#include "DisplayProcessDlg.moc" +#include "ui_DisplayProcessUi.h" + +DisplayProcessDlg::DisplayProcessDlg(QWidget* parent, KSysGuard::Process *process) + : KDialog( parent ) +{ + setObjectName( "Display Process Dialog" ); + setModal( false ); + setCaption( i18n("Monitoring I/O for %1 (%2)", process->pid, process->name) ); + setButtons( Close ); + //enableLinkedHelp( true ); + showButtonSeparator( true ); + + QWidget *widget = new QWidget(this); + setMainWidget(widget); + ui = new Ui_DisplayProcessUi(); + ui->setupUi(widget); + + ui->mTextEdit->setWhatsThis(i18n("The program '%1' (PID: %2) is being monitored for input and output through any file descriptor (stdin, stdout, stderr, open files, network connections, etc.). Data being written by the process is shown in red and data being read by the process is shown in blue.", process->name, process->pid)); + if(!ui->mTextEdit->attach(process->pid)) { + ui->btnDetach->setText(i18n("&Attach")); + ui->btnDetach->setChecked(true); + ui->btnPause->setText(i18n("&Pause")); + ui->btnPause->setChecked(false); + ui->btnPause->setEnabled(false); + + } + connect(ui->btnPause, SIGNAL(toggled(bool)), this, SLOT(slotBtnPause(bool))); + connect(ui->btnDetach, SIGNAL(toggled(bool)), this, SLOT(slotBtnDetach(bool))); +} + +DisplayProcessDlg::~DisplayProcessDlg() { + ui->mTextEdit->detach(); +} +void DisplayProcessDlg::slotButtonClicked(int) +{ + ui->mTextEdit->detach(); + accept(); +} + +QSize DisplayProcessDlg::sizeHint() const { + return QSize(600,600); +} + +void DisplayProcessDlg::slotBtnPause(bool pause) { + if(pause) { + ui->mTextEdit->pauseProcesses(); + ui->btnPause->setText(i18n("&Resume")); + } else { + ui->mTextEdit->resumeProcesses(); + ui->btnPause->setText(i18n("&Pause")); + } +} +void DisplayProcessDlg::slotBtnDetach(bool detach) { + if(detach) { + ui->btnDetach->setText(i18n("&Attach")); + ui->btnDetach->setChecked(true); + ui->btnPause->setText(i18n("&Pause")); + ui->btnPause->setChecked(false); + ui->btnPause->setEnabled(false); + ui->mTextEdit->detach(); + } else { + if(!ui->mTextEdit->reattach()) { + //failed to attached + ui->btnDetach->setText(i18n("&Attach")); + ui->btnDetach->setChecked(true); + ui->btnPause->setText(i18n("&Pause")); + ui->btnPause->setChecked(false); + ui->btnPause->setEnabled(false); + } else + ui->btnDetach->setText(i18n("&Detach")); + } +} + diff --git a/ksysguard/processui/DisplayProcessDlg.h b/ksysguard/processui/DisplayProcessDlg.h new file mode 100644 index 000000000..9ae8438c1 --- /dev/null +++ b/ksysguard/processui/DisplayProcessDlg.h @@ -0,0 +1,53 @@ +/* + KSysGuard, the KDE System Guard + + Copyright (c) 2008 John Tapsell + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This 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 _DisplayProcessDlg_h_ +#define _DisplayProcessDlg_h_ + +#include +#include +#include "processes.h" + +class Ui_DisplayProcessUi; + +class DisplayProcessDlg : public KDialog +{ + Q_OBJECT + +public: + DisplayProcessDlg(QWidget* parent, KSysGuard::Process *process); + ~DisplayProcessDlg(); + /** Returns the default size of the dialog. Reimplmentation from QDialog */ + virtual QSize sizeHint() const; + +public Q_SLOTS: + /** Close button has been clicked. Reimplementation from KDialog */ + virtual void slotButtonClicked(int); + void slotBtnPause(bool pause); + void slotBtnDetach(bool detach); + +private: + Ui_DisplayProcessUi *ui; +}; + +#endif + diff --git a/ksysguard/processui/DisplayProcessUi.ui b/ksysguard/processui/DisplayProcessUi.ui new file mode 100644 index 000000000..3f5368ab5 --- /dev/null +++ b/ksysguard/processui/DisplayProcessUi.ui @@ -0,0 +1,170 @@ + + DisplayProcessUi + + + + 0 + 0 + 681 + 863 + + + + + 0 + + + 0 + + + + + + + + Interpret output as containing VT100 commands. For console-based programs. + + + If this is checked then ANSI escape sequences will be interpreted and not displayed. Useful for when monitoring bash. + + + Interpret ANSI escape sequences + + + true + + + + + + + Show the output from processes launched by this process. + + + Follow fork and clone commands to monitor child processes + + + Monitor child processes + + + true + + + + + + + + + Pause the process and its output + + + Stop reading the output from the process. This will cause the process to be blocked, effectively pausing it. The process can be resumed by resuming, detaching or closing the dialog. + + + &Pause + + + true + + + + + + + Qt::Horizontal + + + + 58 + 27 + + + + + + + + Stop monitoring the process + + + Stop monitoring the process and allow the process to resume running. + + + &Detach + + + true + + + + + + + + + + KMonitorProcessIO + KTextEditVT +
KMonitorProcessIO.h
+
+
+ + mTextEdit + chkColorOutput + chkMonitorChildProcesses + btnPause + btnDetach + + + + + chkColorOutput + toggled(bool) + mTextEdit + setParseAnsiEscapeCodes(bool) + + + 55 + 795 + + + 51 + 254 + + + + + chkMonitorChildProcesses + toggled(bool) + mTextEdit + setIncludeChildProcesses(bool) + + + 281 + 822 + + + 277 + 258 + + + + + btnDetach + toggled(bool) + btnPause + setDisabled(bool) + + + 624 + 847 + + + 75 + 837 + + + + +
diff --git a/ksysguard/processui/KMonitorProcessIO.cpp b/ksysguard/processui/KMonitorProcessIO.cpp new file mode 100644 index 000000000..5dd187082 --- /dev/null +++ b/ksysguard/processui/KMonitorProcessIO.cpp @@ -0,0 +1,330 @@ +/* + KSysGuard, the KDE System Guard + + Copyright (C) 2007 Trent Waddington + Copyright (c) 2008 John Tapsell + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This 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 + aint 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-ksysguard.h" + +#include +#include +#include + +#include +#include +#include +#ifdef HAVE_SYS_PTRACE_H +#include +#endif +#include +#include +#include +#include +#include + +#ifdef __i386__ + #define REG_ORIG_ACCUM(regs) regs.orig_eax + #define REG_ACCUM(regs) regs.eax + #define REG_PARAM1(regs) regs.ebx + #define REG_PARAM2(regs) regs.ecx + #define REG_PARAM3(regs) regs.edx +#endif +#ifdef __amd64__ + #define REG_ORIG_ACCUM(regs) regs.orig_rax + #define REG_ACCUM(regs) regs.rax + #define REG_PARAM1(regs) regs.rdi + #define REG_PARAM2(regs) regs.rsi + #define REG_PARAM3(regs) regs.rdx +#endif +#if defined(__ppc__) || defined(__powerpc__) || defined(__powerpc64__) || defined(__PPC__) || defined(powerpc) + #define REG_ORIG_ACCUM(regs) regs.gpr[0] + #define REG_ACCUM(regs) regs.gpr[3] + #define REG_PARAM1(regs) regs.orig_gpr3 + #define REG_PARAM2(regs) regs.gpr[4] + #define REG_PARAM3(regs) regs.gpr[5] +#ifndef PT_ORIG_R3 + #define PT_ORIG_R3 34 +#endif +#endif +#ifdef __ia64__ + #undef slots + #include + #define REG_ORIG_ACCUM(regs) regs.pt.gr[15] + #define REG_ACCUM(regs) (regs.pt.gr[10] ? -regs.pt.gr[8] : regs.pt.gr[8]) + #define REG_PARAM1(regs) regs.arg[0] + #define REG_PARAM2(regs) regs.arg[1] + #define REG_PARAM3(regs) regs.arg[2] +#endif + +#include "KMonitorProcessIO.h" + +#include "KMonitorProcessIO.moc" + +KMonitorProcessIO::KMonitorProcessIO(QWidget* parent, int pid) + : KTextEditVT( parent ), mPid(pid) +{ + mIncludeChildProcesses = true; + remove_duplicates = false; + + mUpdateInterval = 20; + mTimer.setSingleShot(false); + connect(&mTimer, SIGNAL(timeout()), this, SLOT(update())); + + lastdir = 3; //an invalid direction, so that the color gets set the first time + + setReadOnly(true); + setParseAnsiEscapeCodes(true); + document()->setMaximumBlockCount(100); + mCursor = textCursor(); + + + if(pid == -1) + return; + attach(mPid); +} + +KMonitorProcessIO::~KMonitorProcessIO() { + detach(); +} + +int KMonitorProcessIO::updateInterval() const { + return mUpdateInterval; +} + +void KMonitorProcessIO::setUpdateInterval(int msecs) { + mUpdateInterval = msecs; + if(mTimer.isActive()) { + mTimer.stop(); + mTimer.start(msecs); //Start with the new interval time + } + +} + +void KMonitorProcessIO::detach() { + foreach(int pid, attached_pids) { + detach(pid); + } +} + +int KMonitorProcessIO::attachedPid() const { + return mPid; +} +void KMonitorProcessIO::detach(int pid) { + int status; +#ifdef HAVE_SYS_PTRACE_H + if(!ptrace(PTRACE_DETACH, pid, 0, 0)) { + //successfully detached + } else if(kill(pid, 0) < 0) { + if(errno != ESRCH) + kDebug() << "Something seriously strange when trying to detach."; + } else if (kill(pid, SIGSTOP) < 0) { + if (errno != ESRCH) + kDebug() << "Something seriously strange when trying to detach and then trying to stop the process"; + } else { + for (;;) { + if (waitpid(pid, &status, 0) < 0) { + if (errno != ECHILD) + kDebug() << "Something seriously strange when trying to detach and waiting for process to stop"; + break; + } + if (!WIFSTOPPED(status)) { + /* Au revoir, mon ami. */ + break; + } + if (WSTOPSIG(status) == SIGSTOP) { + //Okay process is now stopped. Lets try detaching again. Silly linux. + if (ptrace(PTRACE_DETACH,pid, 0, 0) < 0) { + if (errno != ESRCH) + kDebug() << "Something seriously strange when trying to detach the second time."; + /* I died trying. */ + } + break; + } + // we didn't manage to stop the process. Lets try continuing it and the stopping it + if (ptrace(PTRACE_CONT, pid, 0, 0) < 0) { + if (errno != ESRCH) + kDebug() << "Something seriously strange when trying to detach and continue"; + break; + } + } + } +#endif + attached_pids.removeAll(pid); + + if(attached_pids.isEmpty()) { + mTimer.stop(); + } +} + +bool KMonitorProcessIO::reattach() { + if(mPid == -1) + return false; + return attach(mPid); +} + +bool KMonitorProcessIO::attach(int pid) { + if(pid == -1) { + //Indicates to detach all + detach(); + return false; + } +#ifdef HAVE_SYS_PTRACE_H + if (ptrace(PTRACE_ATTACH, pid, 0, 0) == -1) { + kDebug() << "Failed to attach to process " << pid; + if(attached_pids.isEmpty()) { + mTimer.stop(); + insertHtml(i18n("
Failed to attach to process %1
", pid)); + return false; + } + } else { + if(attached_pids.isEmpty()) { + //First process added. Automatically start timer + ptrace(PTRACE_SYSCALL, pid, 0, 0); + mTimer.start(mUpdateInterval); + if(mPid == -1) + mPid = pid; + } + attached_pids.append(pid); + } + return true; +#else + return false; +#endif +} + +void KMonitorProcessIO::update(bool modified) +{ +#ifdef HAVE_SYS_PTRACE_H + static QColor writeColor = QColor(255,0,0); + static QColor readColor = QColor(0,0,255); + + int status; + int pid = waitpid(-1, &status, WNOHANG | WUNTRACED | WCONTINUED); + if (pid == -1 || !WIFSTOPPED(status)) { + if(modified) + ensureCursorVisible(); + return; + } +#if defined(__ppc__) || defined(__powerpc__) || defined(__powerpc64__) || defined(__PPC__) || defined(powerpc) + struct pt_regs regs; + regs.gpr[0] = ptrace(PTRACE_PEEKUSER, pid, 4 * PT_R0, 0); + regs.gpr[3] = ptrace(PTRACE_PEEKUSER, pid, 4 * PT_R3, 0); + regs.gpr[4] = ptrace(PTRACE_PEEKUSER, pid, 4 * PT_R4, 0); + regs.gpr[5] = ptrace(PTRACE_PEEKUSER, pid, 4 * PT_R5, 0); + regs.orig_gpr3 = ptrace(PTRACE_PEEKUSER, pid, 4 * PT_ORIG_R3, 0); +#endif +#ifdef __ia64__ + struct { + struct pt_all_user_regs pt; + unsigned long arg[3]; + } regs; + ptrace(PTRACE_GETREGS, pid, 0, ®s.pt); + if (REG_ORIG_ACCUM(regs) >= 0) { + unsigned long *out0 = ia64_rse_skip_regs((unsigned long *)regs.pt.ar[17], -(regs.pt.cfm & 0x7f) + ((regs.pt.cfm >> 7) & 0x7f)); + regs.arg[0] = ptrace(PTRACE_PEEKDATA, pid, ia64_rse_skip_regs(out0, 0), 0); + regs.arg[1] = ptrace(PTRACE_PEEKDATA, pid, ia64_rse_skip_regs(out0, 1), 0); + regs.arg[2] = ptrace(PTRACE_PEEKDATA, pid, ia64_rse_skip_regs(out0, 2), 0); + } +#endif +#if defined __i386__ || defined __amd64__ + struct user_regs_struct regs; + ptrace(PTRACE_GETREGS, pid, 0, ®s); +#endif + /*unsigned int b = ptrace(PTRACE_PEEKTEXT, pid, regs.eip, 0);*/ + if (mIncludeChildProcesses && ( +#ifdef SYS_fork + REG_ORIG_ACCUM(regs) == SYS_fork || +#endif +#ifdef SYS_clone + REG_ORIG_ACCUM(regs) == SYS_clone || +#endif +#ifdef SYS_clone2 + REG_ORIG_ACCUM(regs) == SYS_clone2 || +#endif + 0)) { + if (REG_ACCUM(regs) > 0) + attach(REG_ACCUM(regs)); + } + if ((REG_ORIG_ACCUM(regs) == SYS_read || REG_ORIG_ACCUM(regs) == SYS_write) && (REG_PARAM3(regs) == REG_ACCUM(regs))) { + for (unsigned long i = 0; i < REG_PARAM3(regs); i++) { + union { + unsigned long l; + unsigned char c[sizeof(long)]; + } a; + a.l = ptrace(PTRACE_PEEKDATA, pid, REG_PARAM2(regs) + i, 0); + if(!modified) { + //Before we add text or change the color, make sure we are at the end + moveCursor(QTextCursor::End); + } + if(REG_ORIG_ACCUM(regs) != lastdir) { + if(REG_ORIG_ACCUM(regs) == SYS_read) + setTextColor(readColor); + else + setTextColor(writeColor); + lastdir = REG_ORIG_ACCUM(regs); + } + for (unsigned j = 0; j < sizeof(a.c) && i < REG_PARAM3(regs); i++, j++) { + unsigned char c = a.c[j]; + /** Use the KTextEditVT specific function to parse the character 'c' */ + insertVTChar(QChar(c)); + } + } + modified = true; + } + ptrace(PTRACE_SYSCALL, pid, 0, 0); + update(modified); +#endif +} + +void KMonitorProcessIO::setIncludeChildProcesses(bool include) { + mIncludeChildProcesses = include; +} + +bool KMonitorProcessIO::includeChildProcesses() const { + return mIncludeChildProcesses; +} + + +KMonitorProcessIO::State KMonitorProcessIO::state() const { + if(attached_pids.isEmpty()) + return Detached; + if(mTimer.isActive()) + return AttachedRunning; + return AttachedPaused; +} + +void KMonitorProcessIO::pauseProcesses() { + if(state() == AttachedRunning) { + mTimer.stop(); + } +} +void KMonitorProcessIO::resumeProcesses() { + if(state() == AttachedPaused) + mTimer.start(mUpdateInterval); +} + +void KMonitorProcessIO::setState(State new_state) { + if(new_state == AttachedPaused) pauseProcesses(); + if(new_state == AttachedRunning) resumeProcesses(); + if(new_state == Detached) detach(); +} + + diff --git a/ksysguard/processui/KMonitorProcessIO.h b/ksysguard/processui/KMonitorProcessIO.h new file mode 100644 index 000000000..9a06f2c1a --- /dev/null +++ b/ksysguard/processui/KMonitorProcessIO.h @@ -0,0 +1,115 @@ +/* + KSysGuard, the KDE System Guard + + Copyright (c) 2008 John Tapsell + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This 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 _KMonitorProcessIO_h_ +#define _KMonitorProcessIO_h_ + +#include +#include "KTextEditVT.h" +#include +#include +#include "processes.h" + +class KDE_EXPORT KMonitorProcessIO : public KTextEditVT +{ + Q_OBJECT + Q_PROPERTY( bool includeChildProcesses READ includeChildProcesses WRITE setIncludeChildProcesses ) + Q_PROPERTY( bool updateInterval READ updateInterval WRITE setUpdateInterval ) + Q_PROPERTY( int attachedPid READ attachedPid WRITE attach ) + Q_PROPERTY( State status READ state WRITE setState ) + Q_ENUMS( State ) + +public: + KMonitorProcessIO(QWidget* parent, int pid = -1); + ~KMonitorProcessIO(); + + /** Whether to include the output from child processes. If true, forks and clones will be monitored */ + bool includeChildProcesses() const; + + /** Interval to poll for new ptrace input. Recommended around 20 (milliseconds). Note that the process + * being monitored cannot do anything if it is waiting for us to update. + * Default is 20 (ms) + */ + int updateInterval() const; + /** Set interval to poll for new ptrace input. Recommended around 20 (milliseconds). Note that the process + * being monitored cannot do anything if it is waiting for us to update. + * Default is 20 (ms) + */ + void setUpdateInterval(int msecs); + + /** Detached state indicates that we are not connected to the process and not monitoring it. + * + * AttachedRunning state indicates that we are attached to the process and displaying its output. + * + * AttachedPaused state indicates that we are attached but not reading its output. This will block the process until we resume or detach. + */ + enum State { Detached, AttachedRunning, AttachedPaused }; + + /** Return the current state. */ + KMonitorProcessIO::State state() const; + +public Q_SLOTS: + /** Set whether to include the output from child processes. If true, forks and clones will be monitored */ + void setIncludeChildProcesses(bool include); + /** If the state is in AttachedRunning, change to AttachedPaused. This will block the process until we resume or detach.*/ + void pauseProcesses(); + /** If the state is in AttachedPaused, change to AttachedRunning. This will allow the process to run again. */ + void resumeProcesses(); + /** Stop monitoring all processes*/ + void detach(); + /** Stop monitoring the given process */ + void detach(int pid); + /** Start monitoring the given process. If this is the first process being monitored, the state is set to + * AttachedRunning if possible and attachedPid() will return @p pid + * @return true if successfully reattached. Can fail if process has disappeared or we do not have the right to attach. */ + bool attach(int pid); + /** Reattach the pid that was first attached. + * @return true if successfully reattached. Can fail if process has disappeared or we do not have the right to attach. */ + bool reattach(); + /** Return the main pid that we are monitoring.*/ + int attachedPid() const; + /** Attempts to set the state. Check status() to confirm whether the state has changed successfully. */ + void setState(State new_state); + +Q_SIGNALS: + void finished(); +private Q_SLOTS: + /** Read in the next bit of data and display it. This should be called very frequently. */ + void update(bool modified=false); + +private: + KProcess mIOProcess; + KTextEditVT *mTextEdit; + QTimer mTimer; + int mPid; + QList attached_pids; + + int mUpdateInterval; + bool mIncludeChildProcesses; + bool remove_duplicates; + + unsigned int lastdir; + QTextCursor mCursor; +}; + +#endif + diff --git a/ksysguard/processui/KMonitorProcessIO.widgets b/ksysguard/processui/KMonitorProcessIO.widgets new file mode 100644 index 000000000..8dd9e6e3a --- /dev/null +++ b/ksysguard/processui/KMonitorProcessIO.widgets @@ -0,0 +1,7 @@ + +[KMonitorProcessIO] +ToolTip=Monitors the input and output of a running process. +WhatsThis=A widget for showing the input and output of a running process, including stdin, stdout, stderr and any file descriptors. Be careful as this can make the watched process quite slow. +Group=KSysGuard (KDE) +ConstructorArgs=(parent) +IncludeFile=KMonitorProcessIO.h diff --git a/ksysguard/processui/KTextEditVT.cpp b/ksysguard/processui/KTextEditVT.cpp new file mode 100644 index 000000000..4b505b653 --- /dev/null +++ b/ksysguard/processui/KTextEditVT.cpp @@ -0,0 +1,170 @@ +/* + KSysGuard, the KDE System Guard + + Copyright (C) 2007 Trent Waddington + Copyright (c) 2008 John Tapsell + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This 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 +#include "KTextEditVT.h" + +#include "KTextEditVT.moc" +#include + +KTextEditVT::KTextEditVT(QWidget* parent) + : QTextEdit( parent ) +{ + mParseAnsi = true; + escape_sequence = false; + escape_CSI = false; + escape_OSC = false; + escape_number1 = -1; + escape_number_seperator = false; + escape_number2 = -1; + escape_code = 0; + setFont( KGlobalSettings::fixedFont() ); +} + + +void KTextEditVT::insertVTChar(const QChar & c) { + if(escape_sequence) { + if(escape_CSI || escape_OSC) { + if(c.isDigit()) { + if(!escape_number_seperator) { + if(escape_number1 == -1) + escape_number1 = c.digitValue(); + else + escape_number1 = escape_number1*10 + c.digitValue(); + } else { + if(escape_number2 == -1) + escape_number2 = c.digitValue(); + else + escape_number2 = escape_number2*10 + c.digitValue(); + + } + } else if(c == ';') { + escape_number_seperator = true; + } else if(escape_OSC && c==7) { //Throw away any letters that are not OSC + escape_code = c; + } else if(escape_CSI) + escape_code = c; + } else if(c=='[') { + escape_CSI = true; + } else if(c==']') { + escape_OSC = true; + } + else if(c=='(' || c==')') {} + else + escape_code = c; + if(!escape_code.isNull()) { + //We've read in the whole escape sequence. Now parse it + if(escape_code == 'm') { // change color + switch(escape_number2){ + case 0: //all off + setFontWeight(QFont::Normal); + setTextColor(Qt::black); + break; + case 1: //bold + setFontWeight(QFont::Bold); + break; + case 31: //red + setTextColor(Qt::red); + break; + case 32: //green + setTextColor(Qt::green); + break; + case 33: //yellow + setTextColor(Qt::yellow); + break; + case 34: //blue + setTextColor(Qt::blue); + break; + case 35: //magenta + setTextColor(Qt::magenta); + break; + case 36: //cyan + setTextColor(Qt::cyan); + break; + case -1: + case 30: //black + case 39: //reset + case 37: //white + setTextColor(Qt::black); + break; + } + } + escape_code = 0; + escape_number1 = -1; + escape_number2 = -1; + escape_CSI = false; + escape_OSC = false; + escape_sequence = false; + escape_number_seperator = false; + } + } else if(c == 0x0d) { + insertPlainText(QChar('\n')); + } else if(c.isPrint() || c == '\n') { + insertPlainText(QChar(c)); + } else if(mParseAnsi) { + if(c == 127 || c == 8) { // delete or backspace, respectively + textCursor().deletePreviousChar(); + } else if(c==27) { // escape key + escape_sequence = true; + } else if(c==0x9b) { // CSI - equivalent to esc [ + escape_sequence = true; + escape_CSI = true; + } else if(c==0x9d) { // OSC - equivalent to esc ] + escape_sequence = true; + escape_OSC = true; + } + + } else if(!c.isNull()) { + insertPlainText("["); + QByteArray num; + num.setNum(c.toAscii()); + insertPlainText(num); + insertPlainText("]"); + } +} + +void KTextEditVT::insertVTText(const QByteArray & string) +{ + int size= string.size(); + for(int i =0; i < size; i++) + insertVTChar(QChar(string.at(i))); +} + +void KTextEditVT::insertVTText(const QString & string) +{ + int size= string.size(); + for(int i =0; i < size; i++) + insertVTChar(string.at(i)); +} + +void KTextEditVT::setParseAnsiEscapeCodes(bool parseAnsi) +{ + mParseAnsi = parseAnsi; +} + +bool KTextEditVT::parseAnsiEscapeCodes() const +{ + return mParseAnsi; +} + diff --git a/ksysguard/processui/KTextEditVT.h b/ksysguard/processui/KTextEditVT.h new file mode 100644 index 000000000..360451957 --- /dev/null +++ b/ksysguard/processui/KTextEditVT.h @@ -0,0 +1,104 @@ +/* + KSysGuard, the KDE System Guard + + Copyright (c) 2008 John Tapsell + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This 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 _KTextEditVT_h_ +#define _KTextEditVT_h_ + +#include +#include + +/* + * \class KTextEditVT + * \brief The KTextEditVT class provides a widget that is used to edit and display + * both plain and rich text with the additional function of being able to + * programmatically append VT100 formatted text. For example to display the output + * from console programs. + * + * This class can be used to display the output of VT100 formatted text with + * ANSI escape code - for example output from the command 'ls --color'. + * + * Only a very limited number of ansi escapes sequences will have an affect. Unrecognised + * ansi escape sequences will be ignored and not displayed. Patches are welcome to support + * more of the sequences. + * + * This output can be then be inserted at the current cursor position by calling + * insertVTText(string); + * + * For example: + * + * \code + * insertVTText(QString("Hi") + QChar(08) + "ello"); + * \endcode + * + * will insert the text "Hello" at the current character position. + * (Character 08 is the literal backspace character. Treated as equivalent to character 127) + */ +class KDE_EXPORT KTextEditVT : public QTextEdit +{ + Q_OBJECT + Q_PROPERTY( bool parseAnsiEscapeCodes READ parseAnsiEscapeCodes WRITE setParseAnsiEscapeCodes ) + +public: + KTextEditVT(QWidget* parent); + + /** Whether to parse ANSI display code. If turned off the escape sequence will be shown literally. */ + bool parseAnsiEscapeCodes() const; + +public Q_SLOTS: + /** Set whether to parse ANSI display code. If turned off the escape sequence will be shown literally. */ + void setParseAnsiEscapeCodes(bool displayall); + /** Insert the given string at the current position based on the current state. + * This is interpreted in a VT100 encoding. Backspace and delete will delete the previous character, + * escape sequences can move the cursor and set the current color etc. + * + * This just calls insertVTChar for each character in the string + */ + void insertVTText(const QByteArray & string); + /** Insert the given string at the current position based on the current state. + * This is interpreted in a VT100 encoding. Backspace and delete will delete the previous character, + * escape sequences can move the cursor and set the current color etc. + * + * This just calls insertVTChar for each character in the string + */ + void insertVTText(const QString & string); + + /** Insert the given character at the current position based on the current state. + * This is interpreted in a VT100 encoding. Backspace and delete will delete the previous character, + * escape sequences can move the cursor and set the current color etc. + */ + void insertVTChar(const QChar & c); + + +private: + bool mParseAnsi; + + bool escape_sequence; + bool escape_CSI; + bool escape_OSC; + int escape_number1; + int escape_number2; + bool escape_number_seperator; + QChar escape_code; + +}; + +#endif diff --git a/ksysguard/processui/Messages.sh b/ksysguard/processui/Messages.sh new file mode 100755 index 000000000..7eca6105b --- /dev/null +++ b/ksysguard/processui/Messages.sh @@ -0,0 +1,2 @@ +#! /usr/bin/env bash +$XGETTEXT *.cpp *.cc -o $podir/processui.pot diff --git a/ksysguard/processui/ProcessFilter.cc b/ksysguard/processui/ProcessFilter.cc new file mode 100644 index 000000000..21bd15c66 --- /dev/null +++ b/ksysguard/processui/ProcessFilter.cc @@ -0,0 +1,149 @@ +/* + KSysGuard, the KDE System Guard + + Copyright (c) 2006-2007 John Tapsell + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This 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. + +*/ + + +/* For getuid() */ +#include +#include + +#include + +#include + +#include "ProcessModel.h" +#include "ProcessModel_p.h" +#include "ProcessFilter.h" + +bool ProcessFilter::filterAcceptsRow( int source_row, const QModelIndex & source_parent ) const +{ + if( (mFilter == AllProcesses || mFilter == AllProcessesInTreeForm) + && filterRegExp().isEmpty()) return true; //Shortcut for common case + + ProcessModel *model = static_cast(sourceModel()); + const KSysGuard::Process *process; + if(model->isSimpleMode()) { + if(source_parent.isValid()) { + kDebug() << "Serious error with data. In simple mode, there should be no children"; + return true; + } + process = model->getProcessAtIndex(source_row); + } else { + KSysGuard::Process *parent_process = NULL; + if(source_parent.isValid()) { + parent_process = reinterpret_cast(source_parent.internalPointer()); + Q_ASSERT(parent_process); + } else { + //if(!model->isSimpleMode()) { + parent_process = model->getProcess(0); //Get our 'special' process which should have the root init child + Q_ASSERT(parent_process); + //} + } + if(!model->isSimpleMode() && source_row >= parent_process->children.size()) { + kDebug() << "Serious error with data. Source row requested for a non existent row. Requested " << source_row << " of " << parent_process->children.size() << " for " << parent_process->pid; + return true; + } + + process = parent_process->children.at(source_row); + } + Q_ASSERT(process); + long uid = process->uid; + long euid = process->euid; + + bool accepted = true; + switch(mFilter) { + case AllProcesses: + case AllProcessesInTreeForm: + break; + case SystemProcesses: + if( uid >= 100 && model->canUserLogin(uid)) + accepted = false; + break; + case UserProcesses: + if( (uid < 100 || !model->canUserLogin(uid)) && (euid < 100 || !model->canUserLogin(euid))) + accepted = false; + break; + case OwnProcesses: { + long ownuid = getuid(); + if(uid != ownuid && process->suid != ownuid && process->fsuid != ownuid && euid != ownuid) + accepted = false; + break; + } + case ProgramsOnly: + if(process->tty.isEmpty()) { + if(!model->hasGUIWindow(process->pid)) + accepted = false; + } else { + // login and getty kinda _are_ the tty, so I do not really count them as 'programs'. So make a special case and hide them + // Their ppid are 1 (init) so by checking we try to avoid false matches, and speed up checking overall + if(process->parent_pid == 1 && (process->name == "login" || process->name.endsWith("getty"))) + accepted = false; + } + break; + default: + break; + } + + if(accepted) { + if(filterRegExp().isEmpty()) return true; + + //Allow the user to search by PID + if(QString::number(process->pid).contains(filterRegExp())) return true; + + //None of our tests have rejected it. Pass it on to qsortfilterproxymodel's filter + if(QSortFilterProxyModel::filterAcceptsRow(source_row, source_parent)) + return true; + } + + + //We did not accept this row at all. + + //If we are in flat mode, then give up now + if(mFilter != AllProcessesInTreeForm) + return false; + + //one of our children might be accepted, so accept this row if our children are accepted. + QModelIndex source_index = sourceModel()->index(source_row, 0, source_parent); + for(int i = 0 ; i < sourceModel()->rowCount(source_index); i++) { + if(filterAcceptsRow(i, source_index)) return true; + } + return false; +} + +bool ProcessFilter::lessThan(const QModelIndex &left, const QModelIndex &right) const +{ + if(right.isValid() && left.isValid()) { + Q_ASSERT(left.model()); + Q_ASSERT(right.model()); + QVariant l = (left.model() ? left.model()->data(left, ProcessModel::SortingValueRole) : QVariant()); + QVariant r = (right.model() ? right.model()->data(right, ProcessModel::SortingValueRole) : QVariant()); + if(l.isValid() && r.isValid()) + return l.toDouble() < r.toDouble(); + } + return QSortFilterProxyModel::lessThan(left,right); +} + + +void ProcessFilter::setFilter(State filter) { + mFilter = filter; + filterChanged();//Tell the proxy view to refresh all its information +} +#include "ProcessFilter.moc" diff --git a/ksysguard/processui/ProcessFilter.h b/ksysguard/processui/ProcessFilter.h new file mode 100644 index 000000000..6acbcc4a5 --- /dev/null +++ b/ksysguard/processui/ProcessFilter.h @@ -0,0 +1,56 @@ +/* + KSysGuard, the KDE System Guard + + Copyright (c) 1999, 2000 Chris Schlaeger + Copyright (c) 2006 John Tapsell + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This 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 PROCESSFILTER_H_ +#define PROCESSFILTER_H_ + +#include +#include +#include + +class QModelIndex; + +class KDE_EXPORT ProcessFilter : public QSortFilterProxyModel +{ + Q_OBJECT + Q_ENUMS(State) + + public: + enum State {AllProcesses=0,AllProcessesInTreeForm, SystemProcesses, UserProcesses, OwnProcesses, ProgramsOnly}; + ProcessFilter(QObject *parent=0) : QSortFilterProxyModel(parent) {mFilter = AllProcesses;} + virtual ~ProcessFilter() {} + bool lessThan(const QModelIndex &left, const QModelIndex &right) const; + State filter() const {return mFilter; } + + + public Q_SLOTS: + void setFilter(State index); + + protected: + virtual bool filterAcceptsRow( int source_row, const QModelIndex & source_parent ) const; + + State mFilter; +}; + +#endif + diff --git a/ksysguard/processui/ProcessModel.cc b/ksysguard/processui/ProcessModel.cc new file mode 100644 index 000000000..bdaaa1093 --- /dev/null +++ b/ksysguard/processui/ProcessModel.cc @@ -0,0 +1,1245 @@ +/* + KSysGuard, the KDE System Guard + + Copyright (c) 1999, 2000 Chris Schlaeger + Copyright (c) 2006-2007 John Tapsell + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#define HEADING_X_ICON_SIZE 16 + +#define GET_OWN_ID + +#ifdef GET_OWN_ID +/* For getuid*/ +#include +#include +#endif + +#include "ProcessModel.moc" +#include "ProcessModel_p.moc" +#include "ProcessModel.h" +#include "ProcessModel_p.h" + +#include "processcore/processes.h" +#include "processcore/process.h" + +extern KApplication* Kapp; + +ProcessModelPrivate::ProcessModelPrivate() : mBlankPixmap(HEADING_X_ICON_SIZE,1) +{ + mBlankPixmap.fill(QColor(0,0,0,0)); + mSimple = true; + mIsLocalhost = true; + mMemTotal = -1; + mNumProcessorCores = 1; + mProcesses = NULL; + mShowChildTotals = true; + mIsChangingLayout = false; +} + +ProcessModelPrivate::~ProcessModelPrivate() +{ + if(mProcesses) + KSysGuard::Processes::returnInstance(mHostName); + foreach(WindowInfo wininfo, mPidToWindowInfo) { + delete wininfo.netWinInfo; + } + mProcesses = NULL; +} +ProcessModel::ProcessModel(QObject* parent, const QString &host) + : QAbstractItemModel(parent), d(new ProcessModelPrivate) +{ + KGlobal::locale()->insertCatalog("processui"); //Make sure we include the translation stuff. This needs to be run before any i18n call here + d->q=this; + if(host.isEmpty() || host == "localhost") { + d->mHostName = QString(); + d->mIsLocalhost = true; + } else { + d->mHostName = host; + d->mIsLocalhost = false; + } + setupHeader(); + d->setupProcesses(); + d->setupWindows(); + d->mUnits = UnitsKB; +} + +ProcessModel::~ProcessModel() +{ + delete d; +} + +KSysGuard::Processes *ProcessModel::processController() +{ + return d->mProcesses; +} + +void ProcessModelPrivate::windowRemoved(WId wid) { +#ifdef Q_WS_X11 + long long pid = mWIdToPid.value(wid, 0); + if(pid <= 0) return; + + int count = mPidToWindowInfo.count(pid); + QMultiHash::iterator i = mPidToWindowInfo.find(pid); + while (i != mPidToWindowInfo.end() && i.key() == pid) { + if(i.value().wid == wid) { + delete i.value().netWinInfo; + i = mPidToWindowInfo.erase(i); +// break; + } else + i++; + } + Q_ASSERT(count-1 == mPidToWindowInfo.count(pid) || count == mPidToWindowInfo.count(pid)); + KSysGuard::Process *process = mProcesses->getProcess(pid); + if(!process) return; + + int row; + if(mSimple) + row = process->index; + else + row = process->parent->children.indexOf(process); + QModelIndex index1 = q->createIndex(row, ProcessModel::HeadingName, process); + emit q->dataChanged(index1, index1); + QModelIndex index2 = q->createIndex(row, ProcessModel::HeadingXTitle, process); + emit q->dataChanged(index2, index2); +#endif +} + +void ProcessModelPrivate::setupWindows() { +#ifdef Q_WS_X11 + QList::ConstIterator it; + for ( it = KWindowSystem::windows().begin(); it != KWindowSystem::windows().end(); ++it ) { + windowAdded(*it); + } + + connect( KWindowSystem::self(), SIGNAL( windowChanged (WId, unsigned int )), this, SLOT(windowChanged(WId, unsigned int))); + connect( KWindowSystem::self(), SIGNAL( windowAdded (WId )), this, SLOT(windowAdded(WId))); + connect( KWindowSystem::self(), SIGNAL( windowRemoved (WId )), this, SLOT(windowRemoved(WId))); +#endif +} + +void ProcessModelPrivate::setupProcesses() { + if(mProcesses) { + mWIdToPid.clear(); + mPidToWindowInfo.clear(); + KSysGuard::Processes::returnInstance(mHostName); + q->reset(); + } + + mProcesses = KSysGuard::Processes::getInstance(mHostName); + + connect( mProcesses, SIGNAL( processChanged(KSysGuard::Process *, bool)), this, SLOT(processChanged(KSysGuard::Process *, bool))); + connect( mProcesses, SIGNAL( beginAddProcess(KSysGuard::Process *)), this, SLOT(beginInsertRow( KSysGuard::Process *))); + connect( mProcesses, SIGNAL( endAddProcess()), this, SLOT(endInsertRow())); + connect( mProcesses, SIGNAL( beginRemoveProcess(KSysGuard::Process *)), this, SLOT(beginRemoveRow( KSysGuard::Process *))); + connect( mProcesses, SIGNAL( endRemoveProcess()), this, SLOT(endRemoveRow())); + connect( mProcesses, SIGNAL( beginMoveProcess(KSysGuard::Process *, KSysGuard::Process *)), this, + SLOT( beginMoveProcess(KSysGuard::Process *, KSysGuard::Process *))); + connect( mProcesses, SIGNAL( endMoveProcess()), this, SLOT(endMoveRow())); + mNumProcessorCores = mProcesses->numberProcessorCores(); + if(mNumProcessorCores < 1) mNumProcessorCores=1; //Default to 1 if there was an error getting the number +} + +#ifdef Q_WS_X11 +void ProcessModelPrivate::windowChanged(WId wid, unsigned int properties) +{ + if(! (properties & NET::WMVisibleName || properties & NET::WMName || properties & NET::WMIcon || properties & NET::WMState)) return; + windowAdded(wid); + +} + +void ProcessModelPrivate::windowAdded(WId wid) +{ + foreach(WindowInfo w, mPidToWindowInfo) { + if(w.wid == wid) return; //already added + } + //The name changed + KXErrorHandler handler; + NETWinInfo *info = new NETWinInfo( QX11Info::display(), wid, QX11Info::appRootWindow(), + NET::WMPid | NET::WMVisibleName | NET::WMName | NET::WMState ); + if (handler.error( false ) ) { + delete info; + return; //info is invalid - window just closed or something probably + } + long long pid = info->pid(); + if(pid <= 0) { + delete info; + return; + } + + WindowInfo w; + w.icon = KWindowSystem::icon(wid, HEADING_X_ICON_SIZE, HEADING_X_ICON_SIZE, true); + w.wid = wid; + w.netWinInfo = info; + mPidToWindowInfo.insertMulti(pid, w); + mWIdToPid[wid] = pid; + + KSysGuard::Process *process = mProcesses->getProcess(pid); + if(!process) return; //shouldn't really happen.. maybe race condition etc + int row; + if(mSimple) + row = process->index; + else + row = process->parent->children.indexOf(process); + QModelIndex index1 = q->createIndex(row, ProcessModel::HeadingName, process); + emit q->dataChanged(index1, index1); + QModelIndex index2 = q->createIndex(row, ProcessModel::HeadingXTitle, process); + emit q->dataChanged(index2, index2); +} +#endif + +void ProcessModel::update(int updateDurationMS) { +// kDebug() << "update all processes: " << QTime::currentTime().toString("hh:mm:ss.zzz"); + d->mProcesses->updateAllProcesses(updateDurationMS); + if(d->mMemTotal <= 0) + d->mMemTotal = d->mProcesses->totalPhysicalMemory(); + if(d->mIsChangingLayout) { + d->mIsChangingLayout = false; + emit layoutChanged(); + } +// kDebug() << "finished: " << QTime::currentTime().toString("hh:mm:ss.zzz"); +} + +QString ProcessModelPrivate::getStatusDescription(KSysGuard::Process::ProcessStatus status) const +{ + switch( status) { + case KSysGuard::Process::Running: + return i18n("- Process is doing some work"); + case KSysGuard::Process::Sleeping: + return i18n("- Process is waiting for something to happen"); + case KSysGuard::Process::Stopped: + return i18n("- Process has been stopped. It will not respond to user input at the moment"); + case KSysGuard::Process::Zombie: + return i18n("- Process has finished and is now dead, but the parent process has not cleaned up"); + default: + return QString(); + } +} + +KSysGuard::Process *ProcessModel::getProcessAtIndex(int index) const +{ + Q_ASSERT(d->mSimple); + return d->mProcesses->getAllProcesses().at(index); +} +int ProcessModel::rowCount(const QModelIndex &parent) const +{ + if(d->mSimple) { + if(parent.isValid()) return 0; //In flat mode, none of the processes have children + return d->mProcesses->getAllProcesses().count(); + } + + //Deal with the case that we are showing it as a tree + KSysGuard::Process *process; + if(parent.isValid()) { + if(parent.column() != 0) return 0; //For a treeview we say that only the first column has children + process = reinterpret_cast< KSysGuard::Process * > (parent.internalPointer()); //when parent is invalid, it must be the root level which we set as 0 + } else { + process = d->mProcesses->getProcess(0); + } + Q_ASSERT(process); + int num_rows = process->children.count(); + return num_rows; +} + +int ProcessModel::columnCount ( const QModelIndex & ) const +{ + return d->mHeadings.count(); +} + +bool ProcessModel::hasChildren ( const QModelIndex & parent = QModelIndex() ) const +{ + + if(d->mSimple) { + if(parent.isValid()) return 0; //In flat mode, none of the processes have children + return !d->mProcesses->getAllProcesses().isEmpty(); + } + + //Deal with the case that we are showing it as a tree + KSysGuard::Process *process; + if(parent.isValid()) { + if(parent.column() != 0) return false; //For a treeview we say that only the first column has children + process = reinterpret_cast< KSysGuard::Process * > (parent.internalPointer()); //when parent is invalid, it must be the root level which we set as 0 + } else { + process = d->mProcesses->getProcess(0); + } + Q_ASSERT(process); + bool has_children = !process->children.isEmpty(); + + Q_ASSERT((rowCount(parent) > 0) == has_children); + return has_children; +} + +QModelIndex ProcessModel::index ( int row, int column, const QModelIndex & parent ) const +{ + if(row<0) return QModelIndex(); + if(column<0 || column >= d->mHeadings.count() ) return QModelIndex(); + + if(d->mSimple) { + if( parent.isValid()) return QModelIndex(); + if( d->mProcesses->getAllProcesses().count() <= row) return QModelIndex(); + return createIndex( row, column, d->mProcesses->getAllProcesses().at(row)); + } + + //Deal with the case that we are showing it as a tree + KSysGuard::Process *parent_process = 0; + + if(parent.isValid()) //not valid for init, and init has ppid of 0 + parent_process = reinterpret_cast< KSysGuard::Process * > (parent.internalPointer()); + else + parent_process = d->mProcesses->getProcess(0); + Q_ASSERT(parent_process); + + if(parent_process->children.count() > row) + return createIndex(row,column, parent_process->children[row]); + else + { + return QModelIndex(); + } +} + +bool ProcessModel::isSimpleMode() const +{ + return d->mSimple; +} + +void ProcessModelPrivate::processChanged(KSysGuard::Process *process, bool onlyTotalCpu) +{ + int row; + if(mSimple) + row = process->index; + else + row = process->parent->children.indexOf(process); + + int totalUpdated = 0; + Q_ASSERT(row != -1); //Something has gone very wrong + if(onlyTotalCpu) { + if(mShowChildTotals) { + //Only the total cpu usage changed, so only update that + QModelIndex index = q->createIndex(row, ProcessModel::HeadingCPUUsage, process); + emit q->dataChanged(index, index); + } + return; + } else { + if(process->changes == KSysGuard::Process::Nothing) { + return; //Nothing changed + } + if(process->changes & KSysGuard::Process::Uids) { + totalUpdated++; + QModelIndex index = q->createIndex(row, ProcessModel::HeadingUser, process); + emit q->dataChanged(index, index); + } + if(process->changes & KSysGuard::Process::Tty) { + totalUpdated++; + QModelIndex index = q->createIndex(row, ProcessModel::HeadingTty, process); + emit q->dataChanged(index, index); + } + if(process->changes & (KSysGuard::Process::Usage | KSysGuard::Process::Status) || (process->changes & KSysGuard::Process::TotalUsage && mShowChildTotals)) { + totalUpdated++; + QModelIndex index = q->createIndex(row, ProcessModel::HeadingCPUUsage, process); + emit q->dataChanged(index, index); + } + if(process->changes & KSysGuard::Process::NiceLevels) { + totalUpdated++; + QModelIndex index = q->createIndex(row, ProcessModel::HeadingNiceness, process); + emit q->dataChanged(index, index); + } + if(process->changes & KSysGuard::Process::VmSize) { + totalUpdated++; + QModelIndex index = q->createIndex(row, ProcessModel::HeadingVmSize, process); + emit q->dataChanged(index, index); + } + if(process->changes & (KSysGuard::Process::VmSize | KSysGuard::Process::VmRSS | KSysGuard::Process::VmURSS)) { + totalUpdated+=2; + QModelIndex index = q->createIndex(row, ProcessModel::HeadingMemory, process); + emit q->dataChanged(index, index); + QModelIndex index2 = q->createIndex(row, ProcessModel::HeadingSharedMemory, process); + emit q->dataChanged(index2, index2); + } + + if(process->changes & KSysGuard::Process::Name) { + totalUpdated++; + QModelIndex index = q->createIndex(row, ProcessModel::HeadingName, process); + emit q->dataChanged(index, index); + } + if(process->changes & KSysGuard::Process::Command) { + totalUpdated++; + QModelIndex index = q->createIndex(row, ProcessModel::HeadingCommand, process); + emit q->dataChanged(index, index); + } + if(process->changes & KSysGuard::Process::Login) { + totalUpdated++; + QModelIndex index = q->createIndex(row, ProcessModel::HeadingUser, process); + emit q->dataChanged(index, index); + } + } +} + +void ProcessModelPrivate::beginInsertRow( KSysGuard::Process *process) +{ + Q_ASSERT(process); + if(mIsChangingLayout) { + mIsChangingLayout = false; + emit q->layoutChanged(); + } + + if(mSimple) { + int row = mProcesses->getAllProcesses().count(); + q->beginInsertRows( QModelIndex(), row, row ); + return; + } + + //Deal with the case that we are showing it as a tree + int row = process->parent->children.count(); + QModelIndex parentModelIndex = q->getQModelIndex(process->parent, 0); + + //Only here can we actually change the model. First notify the view/proxy models then modify + q->beginInsertRows(parentModelIndex, row, row); +} +void ProcessModelPrivate::endInsertRow() { + q->endInsertRows(); +} +void ProcessModelPrivate::beginRemoveRow( KSysGuard::Process *process ) +{ + if(mIsChangingLayout) { + mIsChangingLayout = false; + emit q->layoutChanged(); + } + + Q_ASSERT(process); + Q_ASSERT(process->pid > 0); + + if(mSimple) { + return q->beginRemoveRows(QModelIndex(), process->index, process->index); + } else { + int row = process->parent->children.indexOf(process); + if(row == -1) { + kDebug(1215) << "A serious problem occurred in remove row."; + return; + } + + return q->beginRemoveRows(q->getQModelIndex(process->parent,0), row, row); + } +} +void ProcessModelPrivate::endRemoveRow() +{ + q->endRemoveRows(); +} + + +void ProcessModelPrivate::beginMoveProcess(KSysGuard::Process *process, KSysGuard::Process *new_parent) +{ + if(mSimple) return; //We don't need to move processes when in simple mode + if(!mIsChangingLayout) { + emit q->layoutAboutToBeChanged (); + mIsChangingLayout = true; + } + + //FIXME + int current_row = process->parent->children.indexOf(process); + int new_row = new_parent->children.count(); + Q_ASSERT(current_row != -1); + + QList fromIndexes; + QList toIndexes; + for(int i=0; i < q->columnCount(); i++) { + fromIndexes << q->createIndex(current_row, i, process); + toIndexes << q->createIndex(new_row, i, process); + } + q->changePersistentIndexList(fromIndexes, toIndexes); +} +void ProcessModelPrivate::endMoveRow() +{ +} + + +QModelIndex ProcessModel::getQModelIndex( KSysGuard::Process *process, int column) const +{ + Q_ASSERT(process); + int pid = process->pid; + if(pid == 0) return QModelIndex(); //pid 0 is our fake process meaning the very root (never drawn). To represent that, we return QModelIndex() which also means the top element + int row = 0; + if(d->mSimple) { + row = process->index; + } else { + row = process->parent->children.indexOf(process); + } + Q_ASSERT(row != -1); + return createIndex(row, column, process); +} + +QModelIndex ProcessModel::parent ( const QModelIndex & index ) const +{ + if(!index.isValid()) return QModelIndex(); + KSysGuard::Process *process = reinterpret_cast< KSysGuard::Process * > (index.internalPointer()); + Q_ASSERT(process); + + if(d->mSimple) + return QModelIndex(); + else + return getQModelIndex(process->parent,0); +} + +QVariant ProcessModel::headerData(int section, Qt::Orientation orientation, + int role) const +{ + if(orientation != Qt::Horizontal) + return QVariant(); + if(section < 0 || section >= d->mHeadings.count()) + return QVariant(); //is this needed? + switch( role ) { + case Qt::TextAlignmentRole: + { + switch(section) { + case HeadingPid: + case HeadingMemory: + case HeadingSharedMemory: + case HeadingVmSize: + // return QVariant(Qt::AlignRight); + case HeadingUser: + case HeadingCPUUsage: + return QVariant(Qt::AlignCenter); + + } + return QVariant(); + } + case Qt::ToolTipRole: + { + switch(section) { + case HeadingName: + return i18n("The process name"); + case HeadingUser: + return i18n("The user that owns this process"); + case HeadingTty: + return i18n("The controlling terminal that this process is running on."); + case HeadingNiceness: + return i18n("The priority that this process is being run with. Ranges from 19 (very nice, least priority) to -19 (top priority)"); + case HeadingCPUUsage: + if(d->mNumProcessorCores == 1) + return i18n("The current CPU usage of the process."); + else + // i18n: %1 is always greater than 1, so do not worry about + // nonsensical verbosity of the singular part. + return i18np("The current total CPU usage of the process, divided by the %1 processor core in the machine.", "The current total CPU usage of the process, divided by the %1 processor cores in the machine.", d->mNumProcessorCores); + case HeadingVmSize: + return i18n("This is the amount of virtual memory space that the process is using, included shared libraries, graphics memory, files on disk, and so on. This number is almost meaningless."); + case HeadingMemory: + return i18n("This is the amount of real physical memory that this process is using by itself. It does not include any swapped out memory, nor the code size of its shared libraries. This is often the most useful figure to judge the memory use of a program."); + case HeadingSharedMemory: + return i18n("This is the amount of real physical memory that this process's shared libraries are using. This memory is shared among all processes that use this library"); + case HeadingCommand: + return i18n("The command with which this process was launched"); + case HeadingXTitle: + return i18n("The title of any windows that this process is showing"); + case HeadingPid: + return i18n("The unique Process ID that identifies this process"); + default: + return QVariant(); + } + } + case Qt::DisplayRole: + return d->mHeadings[section]; + default: + return QVariant(); + } +} +void ProcessModel::setSimpleMode(bool simple) +{ + if(d->mSimple == simple) return; + + if(!d->mIsChangingLayout) { + emit layoutAboutToBeChanged (); + } + + d->mSimple = simple; + d->mIsChangingLayout = false; + + int flatrow; + int treerow; + QList flatIndexes; + QList treeIndexes; + foreach( KSysGuard::Process *process, d->mProcesses->getAllProcesses()) { + flatrow = process->index; + treerow = process->parent->children.indexOf(process); + flatIndexes.clear(); + treeIndexes.clear(); + + for(int i=0; i < columnCount(); i++) { + flatIndexes << createIndex(flatrow, i, process); + treeIndexes << createIndex(treerow, i, process); + } + if(d->mSimple) //change from tree mode to flat mode + changePersistentIndexList(treeIndexes, flatIndexes); + else // change from flat mode to tree mode + changePersistentIndexList(flatIndexes, treeIndexes); + } + emit layoutChanged(); + +} + +bool ProcessModel::canUserLogin(long long uid ) const +{ + if(uid == 65534) { + //nobody user + return false; + } + + if(!d->mIsLocalhost) return true; //We only deal with localhost. Just always return true for non localhost + + int canLogin = d->mUidCanLogin.value(uid, -1); //Returns 0 if we cannot login, 1 if we can, and the default is -1 meaning we don't know + if(canLogin != -1) return canLogin; //We know whether they can log in + + //We got the default, -1, so we don't know. Look it up + + KUser user(uid); + if(!user.isValid()) { + //for some reason the user isn't recognised. This might happen under certain security situations. + //Just return true to be safe + d->mUidCanLogin[uid] = 1; + return true; + } + QString shell = user.shell(); + if(shell == "/bin/false" ) //FIXME - add in any other shells it could be for false + { + d->mUidCanLogin[uid] = 0; + return false; + } + d->mUidCanLogin[uid] = 1; + return true; +} + +QString ProcessModelPrivate::getTooltipForUser(const KSysGuard::Process *ps) const +{ + QString userTooltip = "

"; + if(!mIsLocalhost) { + userTooltip += i18n("Login Name: %1
", getUsernameForUser(ps->uid, true)); + } else { + KUser user(ps->uid); + if(!user.isValid()) + userTooltip += i18n("This user is not recognized for some reason."); + else { + if(!user.property(KUser::FullName).isValid()) + userTooltip += i18n("%1
", user.property(KUser::FullName).toString()); + userTooltip += i18n("Login Name: %1 (uid: %2)
", user.loginName(), ps->uid); + if(!user.property(KUser::RoomNumber).isValid()) + userTooltip += i18n(" Room Number: %1
", user.property(KUser::RoomNumber).toString()); + if(!user.property(KUser::WorkPhone).isValid()) + userTooltip += i18n(" Work Phone: %1
", user.property(KUser::WorkPhone).toString()); + } + } + if( (ps->uid != ps->euid && ps->euid != -1) || + (ps->uid != ps->suid && ps->suid != -1) || + (ps->uid != ps->fsuid && ps->fsuid != -1)) { + if(ps->euid != -1) + userTooltip += i18n("Effective User: %1
", getUsernameForUser(ps->euid, true)); + if(ps->suid != -1) + userTooltip += i18n("Setuid User: %1
", getUsernameForUser(ps->suid, true)); + if(ps->fsuid != -1) + userTooltip += i18n("File System User: %1
", getUsernameForUser(ps->fsuid, true)); + userTooltip += "
"; + } + if(ps->gid != -1) { + userTooltip += i18n("Group: %1", getGroupnameForGroup(ps->gid)); + if( (ps->gid != ps->egid && ps->egid != -1) || + (ps->gid != ps->sgid && ps->sgid != -1) || + (ps->gid != ps->fsgid && ps->fsgid != -1)) { + if(ps->egid != -1) + userTooltip += i18n("
Effective Group: %1", getGroupnameForGroup(ps->egid)); + if(ps->sgid != -1) + userTooltip += i18n("
Setuid Group: %1", getGroupnameForGroup(ps->sgid)); + if(ps->fsgid != -1) + userTooltip += i18n("
File System Group: %1", getGroupnameForGroup(ps->fsgid)); + } + } + return userTooltip; +} + +QString ProcessModel::getStringForProcess(KSysGuard::Process *process) const { + return i18nc("Short description of a process. PID, name, user", "%1: %2, owned by user %3", (long)(process->pid), process->name, d->getUsernameForUser(process->uid, false)); +} + +QString ProcessModelPrivate::getGroupnameForGroup(long long gid) const { + if(mIsLocalhost) { + QString groupname = KUserGroup(gid).name(); + if(!groupname.isEmpty()) + return i18n("%1 (gid: %2)", groupname, gid); + } + return QString::number(gid); +} + +QString ProcessModelPrivate::getUsernameForUser(long long uid, bool withuid) const { + QString &username = mUserUsername[uid]; + if(username.isNull()) { + if(!mIsLocalhost) { + username = ""; //empty, but not null + } else { + KUser user(uid); + if(!user.isValid()) + username = ""; + else + username = user.loginName(); + } + } + if(username.isEmpty()) + return QString::number(uid); + if(withuid) + return i18n("%1 (uid: %2)", username, (long int)uid); + return username; +} + +QVariant ProcessModel::data(const QModelIndex &index, int role) const +{ + //This function must be super duper ultra fast because it's called thousands of times every few second :( + //I think it should be optomised for role first, hence the switch statement (fastest possible case) + + if (!index.isValid()) { + return QVariant(); + } + if (index.column() >= d->mHeadings.count()) { + return QVariant(); + } + + switch (role){ + case Qt::DisplayRole: { + KSysGuard::Process *process = reinterpret_cast< KSysGuard::Process * > (index.internalPointer()); + switch(index.column()) { + case HeadingName: + return process->name; + case HeadingPid: + return (qlonglong)process->pid; + case HeadingUser: + if(!process->login.isEmpty()) return process->login; + if(process->uid == process->euid) + return d->getUsernameForUser(process->uid, false); + else + return d->getUsernameForUser(process->uid, false) + ", " + d->getUsernameForUser(process->euid, false); + case HeadingNiceness: + return process->niceLevel; + case HeadingTty: + return process->tty; + case HeadingCPUUsage: + { + double total; + if(d->mShowChildTotals && !d->mSimple) total = process->totalUserUsage + process->totalSysUsage; + else total = process->userUsage + process->sysUsage; + total = total / d->mNumProcessorCores; + + if(total < 1 && process->status != KSysGuard::Process::Sleeping && process->status != KSysGuard::Process::Running) + return process->translatedStatus(); //tell the user when the process is a zombie or stopped + if(total < 0.5) + return ""; + + return QString::number((int)(total+0.5)) + '%'; + } + case HeadingMemory: + if(process->vmRSS == 0) return QVariant(QVariant::String); + if(process->vmURSS == -1) { + //If we don't have the URSS (the memory used by only the process, not the shared libraries) + //then return the RSS (physical memory used by the process + shared library) as the next best thing + return formatMemoryInfo(process->vmRSS); + } else { + return formatMemoryInfo(process->vmURSS); + } + case HeadingVmSize: + if(process->vmSize == 0) return QVariant(QVariant::String); + return formatMemoryInfo(process->vmSize); + case HeadingSharedMemory: + if(process->vmRSS - process->vmURSS <= 0 || process->vmURSS == -1) return QVariant(QVariant::String); + return formatMemoryInfo(process->vmRSS - process->vmURSS); + case HeadingCommand: + { + return process->command; +// It would be nice to embolden the process name in command, but this requires that the itemdelegate to support html text +// QString command = process->command; +// command.replace(process->name, "" + process->name + ""); +// return "" + command; + } +#ifdef Q_WS_X11 + case HeadingXTitle: + { + if(!d->mPidToWindowInfo.contains(process->pid)) return QVariant(QVariant::String); + WindowInfo w = d->mPidToWindowInfo.value(process->pid); + if(!w.netWinInfo) return QVariant(QVariant::String); + const char *name = w.netWinInfo->visibleName(); + if( !name || name[0] == 0 ) + name = w.netWinInfo->name(); + if(name && name[0] != 0) + return QString::fromUtf8(name); + return QVariant(QVariant::String); + } +#endif + default: + return QVariant(); + } + break; + } + case Qt::ToolTipRole: { + KSysGuard::Process *process = reinterpret_cast< KSysGuard::Process * > (index.internalPointer()); + QString tracer; + if(process->tracerpid > 0) { + KSysGuard::Process *process_tracer = d->mProcesses->getProcess(process->tracerpid); + if(process_tracer) { //it is possible for this to be not the case in certain race conditions + KSysGuard::Process *process_tracer = d->mProcesses->getProcess(process->tracerpid); + tracer = i18nc("tooltip. name,pid ","This process is being debugged by %1 (%2)", process_tracer->name, (long int)process->tracerpid); + } + } + switch(index.column()) { + case HeadingName: { + QString tooltip = "

"; + /* It would be nice to be able to show the icon in the tooltip, but Qt4 won't let us put + * a picture in a tooltip :( + + QIcon icon; + if(mPidToWindowInfo.contains(process->pid)) { + WId wid; + wid = mPidToWindowInfo[process->pid].wid; + icon = KWindowSystem::icon(wid); + } + if(icon.isValid()) { + tooltip = i18n("
%1", icon); + } + */ + if(process->parent_pid == 0) { + //Give a quick explanation of init and kthreadd + if(process->name == "init") { + tooltip += i18n("Init is the parent of all other processes and cannot be killed.
"); + } else if(process->name == "kthreadd") { + tooltip += i18n("KThreadd manages kernel threads. The children processes run in the kernel, controlling hard disk access, etc.
"); + } + tooltip += i18nc("name column tooltip. first item is the name","%1
Process ID: %2", process->name, (long int)process->pid); + } + else { + KSysGuard::Process *parent_process = d->mProcesses->getProcess(process->parent_pid); + if(parent_process) { //it should not be possible for this process to not exist, but check just incase + tooltip = i18nc("name column tooltip. first item is the name","%1
Process ID: %2
Parent: %3
Parent's ID: %4", process->name, (long int)process->pid, parent_process->name, (long int)process->parent_pid); + } else { + tooltip = i18nc("name column tooltip. first item is the name","%1
Process ID: %2
Parent's ID: %3", process->name, (long int)process->pid, (long int)process->parent_pid); + } + } + if(!process->command.isEmpty()) { + tooltip+= i18n("
Command: %1", process->command); + } + if(!process->tty.isEmpty()) + tooltip += i18n( "
Running on: %1", QString(process->tty)); + if(!tracer.isEmpty()) + return tooltip + "
" + tracer; + return tooltip; + } + + case HeadingCommand: { + QString tooltip = + i18n("This process was run with the following command:
%1", process->command); + if(!process->tty.isEmpty()) + tooltip += i18n( "

Running on: %1", QString(process->tty)); + if(tracer.isEmpty()) return tooltip; + return tooltip + "
" + tracer; + } + case HeadingUser: { + if(!tracer.isEmpty()) + return d->getTooltipForUser(process) + "
" + tracer; + return d->getTooltipForUser(process); + } + case HeadingNiceness: { + QString tooltip = "

"; + switch(process->scheduler) { + case KSysGuard::Process::Other: + case KSysGuard::Process::Batch: + tooltip += i18n("Nice level: %1 (%2)", process->niceLevel, process->niceLevelAsString() ); + break; + case KSysGuard::Process::RoundRobin: + case KSysGuard::Process::Fifo: + tooltip += i18n("Scheduler priority: %1", process->niceLevel); + break; + } + if(process->scheduler != KSysGuard::Process::Other) + tooltip += i18n("
Scheduler: %1", process->schedulerAsString()); + + if(process->ioPriorityClass != KSysGuard::Process::None) { + if((process->ioPriorityClass == KSysGuard::Process::RealTime || process->ioPriorityClass == KSysGuard::Process::BestEffort) && process->ioniceLevel != -1) + tooltip += i18n("
I/O Nice level: %1 (%2)", process->ioniceLevel, process->ioniceLevelAsString() ); + tooltip += i18n("
I/O Class: %1", process->ioPriorityClassAsString() ); + } + if(tracer.isEmpty()) return tooltip; + return tooltip + "
" + tracer; + } + case HeadingCPUUsage: { + QString tooltip = ki18n("

" + "Process status: %1 %2
" + "User CPU usage: %3%
System CPU usage: %4%") + .subs(process->translatedStatus()) + .subs(d->getStatusDescription(process->status)) + .subs((float)(process->userUsage) / d->mNumProcessorCores) + .subs((float)(process->sysUsage) / d->mNumProcessorCores) + .toString(); + + if(process->numChildren > 0) { + tooltip += ki18n("
Number of children: %1
Total User CPU usage: %2%
" + "Total System CPU usage: %3%
Total CPU usage: %4%") + .subs(process->numChildren) + .subs((float)(process->totalUserUsage)/ d->mNumProcessorCores) + .subs((float)(process->totalSysUsage) / d->mNumProcessorCores) + .subs((float)(process->totalUserUsage + process->totalSysUsage) / d->mNumProcessorCores) + .toString(); + } + if(process->userTime > 0) + tooltip += ki18n("

CPU time spent running as user: %1 seconds") + .subs(process->userTime / 100.0, 0, 'f', 1) + .toString(); + if(process->sysTime > 0) + tooltip += ki18n("
CPU time spent running in kernel: %1 seconds") + .subs(process->sysTime / 100.0, 0, 'f', 1) + .toString(); + if(process->niceLevel != 0) + tooltip += i18n("
Nice level: %1 (%2)", process->niceLevel, process->niceLevelAsString() ); + if(process->ioPriorityClass != KSysGuard::Process::None) { + if((process->ioPriorityClass == KSysGuard::Process::RealTime || process->ioPriorityClass == KSysGuard::Process::BestEffort) && process->ioniceLevel != -1) + tooltip += i18n("
I/O Nice level: %1 (%2)", process->ioniceLevel, process->ioniceLevelAsString() ); + tooltip += i18n("
I/O Class: %1", process->ioPriorityClassAsString() ); + } + + if(!tracer.isEmpty()) + return tooltip + "
" + tracer; + return tooltip; + } + case HeadingVmSize: { + return QVariant(); + } + case HeadingMemory: { + QString tooltip = "

"; + if(process->vmURSS != -1) { + //We don't have information about the URSS, so just fallback to RSS + if(d->mMemTotal > 0) + tooltip += i18n("Memory usage: %1 out of %2 (%3 %)
", KGlobal::locale()->formatByteSize(process->vmURSS * 1024), KGlobal::locale()->formatByteSize(d->mMemTotal*1024), process->vmURSS*100/d->mMemTotal); + else + tooltip += i18n("Memory usage: %1
", KGlobal::locale()->formatByteSize(process->vmURSS * 1024)); + } + if(d->mMemTotal > 0) + tooltip += i18n("RSS Memory usage: %1 out of %2 (%3 %)", KGlobal::locale()->formatByteSize(process->vmRSS * 1024), KGlobal::locale()->formatByteSize(d->mMemTotal*1024), process->vmRSS*100/d->mMemTotal); + else + tooltip += i18n("RSS Memory usage: %1", KGlobal::locale()->formatByteSize(process->vmRSS * 1024)); + return tooltip; + } + case HeadingSharedMemory: { + QString tooltip = "

"; + if(process->vmURSS == -1) { + tooltip += i18n("Your system does not seem to have this information available to be read."); + return tooltip; + } + if(d->mMemTotal >0) + tooltip += i18n("Shared library memory usage: %1 out of %2 (%3 %)", KGlobal::locale()->formatByteSize((process->vmRSS - process->vmURSS) * 1024), KGlobal::locale()->formatByteSize(d->mMemTotal*1024), (process->vmRSS-process->vmURSS)*100/d->mMemTotal); + else + tooltip += i18n("Shared library memory usage: %1", KGlobal::locale()->formatByteSize((process->vmRSS - process->vmURSS) * 1024)); + + return tooltip; + } + case HeadingXTitle: { + QString tooltip; + QList values = d->mPidToWindowInfo.values(process->pid); + if(values.isEmpty()) return QVariant(QVariant::String); + for(int i = 0; i< values.size(); i++) { + WindowInfo w = values[i]; + if(w.netWinInfo) { + const char *name = w.netWinInfo->visibleName(); + if( !name || name[0] == 0 ) + name = w.netWinInfo->name(); + if(name && name[0] != 0) { + if( i==0 && values.size()==1) + return QString::fromUtf8(name); + tooltip += "

  • " + QString::fromUtf8(name) + "
  • "; + } + } + } + if(!tooltip.isEmpty()) + return "

      " + tooltip + "
    "; + return QVariant(QVariant::String); + } + + default: + return QVariant(QVariant::String); + } + } + case Qt::TextAlignmentRole: + switch(index.column() ) { + case HeadingUser: + case HeadingCPUUsage: + return QVariant(Qt::AlignCenter); + case HeadingPid: + case HeadingMemory: + case HeadingSharedMemory: + case HeadingVmSize: + return QVariant(Qt::AlignRight); + } + return QVariant(); + case UidRole: { + if(index.column() != 0) return QVariant(); //If we query with this role, then we want the raw UID for this. + KSysGuard::Process *process = reinterpret_cast< KSysGuard::Process * > (index.internalPointer()); + return process->uid; + } + case SortingValueRole: { + //We have a special understanding with the filter sort. This returns an int (in a qvariant) that can be sorted by + KSysGuard::Process *process = reinterpret_cast< KSysGuard::Process * > (index.internalPointer()); + Q_ASSERT(process); + switch(index.column()) { + case HeadingUser: { + //Sorting by user will be the default and the most common. + //We want to sort in the most useful way that we can. We need to return a number though. + //This code is based on that sorting ascendingly should put the current user at the top + // + //First the user we are running as should be at the top. We add 0 for this + //Then any other users in the system. We add 100,000,000 for this (remember it's ascendingly sorted) + //Then at the bottom the 'system' processes. We add 200,000,000 for this + // + //We subtract the uid to sort ascendingly by that, then subtract the cpu usage to sort by that, then finally subtract the memory + + long long base = 0; + long long memory = 0; + if(process->vmURSS != -1) memory = process->vmURSS; + else memory = process->vmRSS; + if(d->mIsLocalhost && process->uid == getuid()) + base = 0; //own user + else if(process->uid < 100 || !canUserLogin(process->uid)) + base = 200000000 - process->uid * 10000; //system user + else + base = 100000000 - process->uid * 10000; + //One special exception is a traced process since that's probably important. We should put that at the top + if(process->tracerpid >0) return base - 9999 ; + int cpu; + if(d->mSimple || !d->mShowChildTotals) + cpu = process->userUsage + process->sysUsage; + else + cpu = process->totalUserUsage + process->totalSysUsage; + if(cpu == 0 && process->status != KSysGuard::Process::Running && process->status != KSysGuard::Process::Sleeping) + cpu = 1; //stopped or zombied processes should be near the top of the list + bool hasWindow = d->mPidToWindowInfo.contains(process->pid); + //However we can of course have lots of processes with the same user. Next we sort by CPU. + if(d->mMemTotal>0) + return (double)(base - (cpu*100) -(hasWindow?50:0) - memory*100.0/d->mMemTotal); + else + return (double)(base - (cpu*100) -(hasWindow?50:0)); + } + case HeadingCPUUsage: { + int cpu; + if(d->mSimple || !d->mShowChildTotals) + cpu = process->userUsage + process->sysUsage; + else + cpu = process->totalUserUsage + process->totalSysUsage; + if(cpu == 0 && process->status != KSysGuard::Process::Running && process->status != KSysGuard::Process::Sleeping) + cpu = 1; //stopped or zombied processes should be near the top of the list + return -cpu; + } + case HeadingMemory: + if(process->vmURSS == -1) + return (long long)-process->vmRSS; + else + return (long long)-process->vmURSS; + case HeadingVmSize: + return (long long)-process->vmSize; + case HeadingSharedMemory: + if(process->vmURSS == -1) return (long long)0; + return (long long)-(process->vmRSS - process->vmURSS); + } + return QVariant(); + } +#ifdef Q_WS_X11 + case WindowIdRole: { + KSysGuard::Process *process = reinterpret_cast< KSysGuard::Process * > (index.internalPointer()); + if(!d->mPidToWindowInfo.contains(process->pid)) return QVariant(); + WindowInfo w = d->mPidToWindowInfo.value(process->pid); + return (int)w.wid; + } +#endif + case TotalMemoryRole: { + return d->mMemTotal; + } + case NumberOfProcessorsRole: { + return d->mNumProcessorCores; + } + case Qt::DecorationRole: { + if(index.column() == HeadingName) { + KSysGuard::Process *process = reinterpret_cast< KSysGuard::Process * > (index.internalPointer()); + if(!d->mPidToWindowInfo.contains(process->pid)) { + if(d->mSimple) //When not in tree mode, we need to pad the name column where we do not have an icon + return QIcon(d->mBlankPixmap); + else //When in tree mode, the padding looks pad, so do not pad in this case + return QVariant(); + } + + WindowInfo w = d->mPidToWindowInfo.value(process->pid); + if(w.icon.isNull()) + return QIcon(d->mBlankPixmap); + return w.icon; + + } else if (index.column() == HeadingCPUUsage) { + KSysGuard::Process *process = reinterpret_cast< KSysGuard::Process * > (index.internalPointer()); + if(process->status == KSysGuard::Process::Stopped || process->status == KSysGuard::Process::Zombie) { + QPixmap pix = KIconLoader::global()->loadIcon("button_cancel", KIconLoader::Small, + KIconLoader::SizeSmall, KIconLoader::DefaultState, QStringList(), + 0L, true); + + } + } + return QVariant(); + } + case Qt::BackgroundRole: { + if(index.column() != HeadingUser) return QVariant(); + KSysGuard::Process *process = reinterpret_cast< KSysGuard::Process * > (index.internalPointer()); + if(process->tracerpid >0) { + //It's being debugged, so probably important. Let's mark it as such + return QColor("yellow"); + } + if(d->mIsLocalhost && process->uid == getuid()) { //own user + return QColor(0, 208, 214, 50); + } + if(process->uid < 100 || !canUserLogin(process->uid)) + return QColor(218, 220,215, 50); //no color for system tasks + //other users + return QColor(2, 154, 54, 50); + } + case Qt::FontRole: { + if(index.column() == HeadingCPUUsage) { + KSysGuard::Process *process = reinterpret_cast< KSysGuard::Process * > (index.internalPointer()); + if(process->userUsage == 0) { + QFont font; + font.setItalic(true); + return font; + } + } + return QVariant(); + } + default: //This is a very very common case, so the route to this must be very minimal + return QVariant(); + } + + return QVariant(); //never get here, but make compilier happy +} + +bool ProcessModel::hasGUIWindow(long long pid) const +{ + return d->mPidToWindowInfo.contains(pid); +} + +bool ProcessModel::isLocalhost() const +{ + return d->mIsLocalhost; +} + + +void ProcessModel::setupHeader() { + QStringList headings; + headings << i18nc("process heading", "Name"); + headings << i18nc("process heading", "User Name"); + headings << i18nc("process heading", "PID"); + headings << i18nc("process heading", "TTY"); + headings << i18nc("process heading", "Niceness"); + // xgettext: no-c-format + headings << i18nc("process heading", "CPU %"); + headings << i18nc("process heading", "Virtual Size"); + headings << i18nc("process heading", "Memory"); + headings << i18nc("process heading", "Shared Mem"); + headings << i18nc("process heading", "Command"); +#ifdef Q_WS_X11 + headings << i18nc("process heading", "Window Title"); +#endif + + if(d->mHeadings.isEmpty()) { // If it's empty, this is the first time this has been called, so insert the headings + beginInsertColumns(QModelIndex(), 0, headings.count()-1); + d->mHeadings = headings; + endInsertColumns(); + } else { + // This was called to retranslate the headings. Just use the new translations and call headerDataChanged + Q_ASSERT(d->mHeadings.count() == headings.count()); + d->mHeadings = headings; + headerDataChanged(Qt::Horizontal, 0 , headings.count()-1); + + } +} + +void ProcessModel::retranslateUi() +{ + setupHeader(); +} + +KSysGuard::Process *ProcessModel::getProcess(long long pid) { + return d->mProcesses->getProcess(pid); +} + +bool ProcessModel::showTotals() const { + return d->mShowChildTotals; +} + +void ProcessModel::setShowTotals(bool showTotals) //slot +{ + if(showTotals == d->mShowChildTotals) return; + d->mShowChildTotals = showTotals; + + QModelIndex index; + foreach( KSysGuard::Process *process, d->mProcesses->getAllProcesses()) { + if(process->numChildren > 0) { + int row; + if(d->mSimple) + row = process->index; + else + row = process->parent->children.indexOf(process); + index = createIndex(row, HeadingCPUUsage, process); + emit dataChanged(index, index); + } + } +} + +long long ProcessModel::totalMemory() const +{ + return d->mMemTotal; +} +void ProcessModel::setUnits(Units units) +{ + d->mUnits = units; +} +ProcessModel::Units ProcessModel::units() const +{ + return (Units) d->mUnits; +} + +QString ProcessModel::formatMemoryInfo(long amountInKB) const +{ + switch(d->mUnits) { + case UnitsKB: + return i18n("%1 K", amountInKB); + case UnitsMB: + return i18n("%1 M", (amountInKB+512)/1024); //Round to nearest megabyte + case UnitsGB: + return i18n("%1 G", (amountInKB+512*1024)/(1024*1024)); //Round to nearest gigabyte + } + return ""; //error +} + +QString ProcessModel::hostName() const { + return d->mHostName; +} + diff --git a/ksysguard/processui/ProcessModel.h b/ksysguard/processui/ProcessModel.h new file mode 100644 index 000000000..a17eb429c --- /dev/null +++ b/ksysguard/processui/ProcessModel.h @@ -0,0 +1,143 @@ +/* + KSysGuard, the KDE System Guard + + Copyright (c) 1999, 2000 Chris Schlaeger + Copyright (c) 2006 John Tapsell + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This 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 PROCESSMODEL_H_ +#define PROCESSMODEL_H_ + +#include + +#include + +namespace KSysGuard { + class Processes; + class Process; +} + +class ProcessModelPrivate; +class KDE_EXPORT ProcessModel : public QAbstractItemModel +{ + Q_OBJECT + Q_ENUMS(Units) + +public: + ProcessModel(QObject* parent = 0, const QString &host = QString() ); + virtual ~ProcessModel(); + + /* Functions for our Model for QAbstractItemModel*/ + int rowCount(const QModelIndex &parent = QModelIndex()) const; + int columnCount ( const QModelIndex & parent = QModelIndex() ) const; + QVariant data(const QModelIndex &index, int role) const; + QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; + QModelIndex index ( int row, int column, const QModelIndex & parent = QModelIndex() ) const; + QModelIndex parent ( const QModelIndex & index ) const; + + bool hasChildren ( const QModelIndex & parent) const; + + /* Functions for setting the model */ + + /** Setup the column headings by inserting the appropriate headings into the model. + * Can be called more than once to retranslate the headings if the system language changes. + */ + void setupHeader(); + + /** Update data. You can pass in the time between updates to only update if there hasn't + * been an update within the last @p updateDurationMSecs milliseconds */ + void update(int updateDurationMSecs = 0); + + /** Return a string with the pid of the process and the name of the process. E.g. 13343: ksyguard + */ + QString getStringForProcess(KSysGuard::Process *process) const; + KSysGuard::Process *getProcess(long long pid); + + /** This is used from ProcessFilter to get the process at a given index when in flat mode */ + KSysGuard::Process *getProcessAtIndex(int index) const; + + /** Returns whether this user can log in or not. + * @see mUidCanLogin + */ + bool canUserLogin(long long uid) const; + /** In simple mode, everything is flat, with no icons, few if any colors, no xres etc. + * This can be changed at any time. It is a fairly quick operation. Basically it resets the model + */ + void setSimpleMode(bool simple); + /** In simple mode, everything is flat, with no icons, few if any colors, no xres etc + */ + bool isSimpleMode() const; + + /** Returns the total amount of physical memory in the machine. */ + long long totalMemory() const; + + /** This returns a QModelIndex for the given process. It has to look up the parent for this pid, find the offset this + * pid is from the parent, and return that. It's not that slow, but does involve a couple of hash table lookups. + */ + QModelIndex getQModelIndex ( KSysGuard::Process *process, int column) const; + + /** Whether this is showing the processes for the current machine + */ + bool isLocalhost() const; + + /** The host name that this widget is showing the processes of */ + QString hostName() const; + + /** Whether this process has a GUI window */ + bool hasGUIWindow(long long pid) const; + + /** Returns for process controller pointer for this model + */ + KSysGuard::Processes *processController(); ///The processes instance + + /** The headings in the model. The order here is the order that they are shown + * in. If you change this, make sure you also change the + * setup header function, and make sure you increase PROCESSHEADERVERSION. This will ensure + * that old saved settings won't be used + */ +#define PROCESSHEADERVERSION 1 + enum { HeadingName=0, HeadingUser, HeadingPid, HeadingTty, HeadingNiceness, HeadingCPUUsage, HeadingVmSize, HeadingMemory, HeadingSharedMemory, HeadingCommand, HeadingXTitle }; + enum { UidRole = Qt::UserRole, SortingValueRole, WindowIdRole, TotalMemoryRole, NumberOfProcessorsRole }; + + bool showTotals() const; + + /** When displaying memory sizes, this is the units it should be displayed in */ + enum Units { UnitsKB, UnitsMB, UnitsGB }; + /** Set the units memory sizes etc should be displayed in */ + void setUnits(Units units); + /** The units memory sizes etc should be displayed in */ + Units units() const; + /** Take an amount in kb, and return a string in the units set by setUnits() */ + QString formatMemoryInfo(long amountInKB) const; + + /** Retranslate the GUI, for when the system language changes */ + void retranslateUi(); + +public Q_SLOTS: + + /** Whether to show the total cpu for the process plus all of its children */ + void setShowTotals(bool showTotals); + +private: + ProcessModelPrivate* const d; + friend class ProcessModelPrivate; +}; + +#endif + diff --git a/ksysguard/processui/ProcessModel_p.h b/ksysguard/processui/ProcessModel_p.h new file mode 100644 index 000000000..9b457914a --- /dev/null +++ b/ksysguard/processui/ProcessModel_p.h @@ -0,0 +1,186 @@ +/* + KSysGuard, the KDE System Guard + + Copyright (c) 2006-2007 John Tapsell + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This 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 PROCESSMODEL_P_H_ +#define PROCESSMODEL_P_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#ifdef Q_WS_X11 +#include +#include +#include +#include +#include +#endif + +#include "processcore/process.h" + + +#ifdef Q_WS_X11 +struct WindowInfo { + QPixmap icon; + WId wid; + NETWinInfo *netWinInfo; +}; + +#endif + + +class ProcessModel; +class ProcessModelPrivate : public QObject +{ + Q_OBJECT +public: + ProcessModelPrivate(); + ~ProcessModelPrivate(); +public slots: + +#ifdef Q_WS_X11 + /** When an X window is changed, this is called */ + void windowChanged(WId wid, unsigned int properties); + /** When an X window is created, this is called + */ + void windowAdded(WId wid); + /** When an X window is closed, this is called + */ + void windowRemoved(WId wid); +#endif + + /** Change the data for a process. This is called from KSysGuard::Processes + * if @p onlyCpuOrMem is set, only the total cpu usuage is updated. + * process->changes contains a bitfield of what has been changed + */ + void processChanged(KSysGuard::Process *process, bool onlyCpuOrMem); + /** Called from KSysGuard::Processes + * This indicates we are about to insert a process in the model. Emit the appropriate signals + */ + void beginInsertRow( KSysGuard::Process *parent); + /** Called from KSysGuard::Processes + * We have finished inserting a process + */ + void endInsertRow(); + /** Called from KSysGuard::Processes + * This indicates we are about to remove a process in the model. Emit the appropriate signals + */ + void beginRemoveRow( KSysGuard::Process *process); + /** Called from KSysGuard::Processes + * We have finished removing a process + */ + void endRemoveRow(); + /** Called from KSysGuard::Processes + * This indicates we are about to move a process in the model from one parent process to another. Emit the appropriate signals + */ + void beginMoveProcess(KSysGuard::Process *process, KSysGuard::Process *new_parent); + /** Called from KSysGuard::Processes + * We have finished moving a process + */ + void endMoveRow(); + +public: + /** On X11 system, connects to the signals emitted when windows are created/destroyed */ + void setupWindows(); + /** Connects to the host */ + void setupProcesses(); + /** A mapping of running,stopped,etc to a friendly description like 'Stopped, either by a job control signal or because it is being traced.'*/ + QString getStatusDescription(KSysGuard::Process::ProcessStatus status) const; + + /** Return a qt markup tooltip string for a local user. It will have their full name etc. + * This will be slow the first time, as it practically indirectly reads the whole of /etc/passwd + * But the second time will be as fast as hash lookup as we cache the result + */ + inline QString getTooltipForUser(const KSysGuard::Process *process) const; + + /** Return a username for a local user if it can, otherwise just their uid. + * This may have been given from the result of "ps" (but not necessarily). If it's not found, then it + * needs to find out the username from the uid. This will be slow the first time, as it practically indirectly reads the whole of /etc/passwd + * But the second time will be as fast as hash lookup as we cache the result + * + * If withuid is set, and the username is found, return: "username (Uid: uid)" + */ + inline QString getUsernameForUser(long long uid, bool withuid) const; + + /** Return the groupname for a given gid. This is in the form of "gid" if not known, or + * "groupname (Uid: gid)" if known. + */ + inline QString getGroupnameForGroup(long long gid) const; + /** @see setIsLocalhost */ + bool mIsLocalhost; + + /** A caching hash for tooltips for a user. + * @see getTooltipForUser */ + mutable QHash mUserTooltips; + + /** A caching hash for username for a user uid, or just their uid if it can't be found (as a long long) + * @see getUsernameForUser */ + mutable QHash mUserUsername; + + /** A mapping of a user id to whether this user can log in. We have to guess based on the shell. All are set to true to non localhost. + * It is set to: + * 0 if the user cannot login + * 1 is the user can login + * The reason for using an int and not a bool is so that we can do mUidCanLogin.value(uid,-1) and thus we get a tristate for whether + * they are logged in, not logged in, or not known yet. + * */ + mutable QHash mUidCanLogin; + + + /** A translated list of headings (column titles) in the order we want to display them. Used in headerData() */ + QStringList mHeadings; + + QMultiHash< long long, WindowInfo> mPidToWindowInfo; ///Map a process pid to X window info if available + QHash< WId, long long> mWIdToPid; ///Map an X window id to a process pid + + + bool mShowChildTotals; ///If set to true, a parent will return the CPU usage of all its children recursively + + bool mSimple; ///In simple mode, the model returns everything as flat, with no icons, etc. This is set by changing cmbFilter + + QTime mLastUpdated; ///Time that we last updated the processes. + + long long mMemTotal; /// the total amount of physical memory in kb in the machine. We can used this to determine the percentage of memory an app is using + int mNumProcessorCores; /// The number of (enabled) processor cores in the this machine + + KSysGuard::Processes *mProcesses; ///The processes instance + + bool mIsChangingLayout; + + QPixmap mBlankPixmap; ///Used to pad out process names which don't have an icon + + /** When displaying memory sizes, this is the units it should be displayed in */ + int mUnits; + + /** The hostname */ + QString mHostName; + + ProcessModel* q; +}; + +#endif diff --git a/ksysguard/processui/ProcessWidgetUI.ui b/ksysguard/processui/ProcessWidgetUI.ui new file mode 100644 index 000000000..db0b81068 --- /dev/null +++ b/ksysguard/processui/ProcessWidgetUI.ui @@ -0,0 +1,155 @@ + + ProcessWidget + + + + 0 + 0 + 490 + 472 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + false + + + + 0 + 0 + + + + &Kill Process + + + false + + + + + + + QLineEdit { padding-right: 16; } + + + false + + + Quick search + + + true + + + + + + + + 0 + 0 + + + + 10 + + + QComboBox::AdjustToContentsOnFirstShow + + + + All Processes + + + + + All Processes, Tree + + + + + System Processes + + + + + User Processes + + + + + Own Processes + + + + + Programs Only + + + + + + + + + + QAbstractItemView::NoEditTriggers + + + true + + + QAbstractItemView::ExtendedSelection + + + QAbstractItemView::SelectRows + + + false + + + true + + + true + + + true + + + false + + + true + + + + + + + + KLineEdit + QLineEdit +
    klineedit.h
    +
    +
    + + +
    diff --git a/ksysguard/processui/ReniceDlg.cc b/ksysguard/processui/ReniceDlg.cc new file mode 100644 index 000000000..628d99232 --- /dev/null +++ b/ksysguard/processui/ReniceDlg.cc @@ -0,0 +1,180 @@ +/* + KSysGuard, the KDE System Guard + + Copyright (c) 1999 Chris Schlaeger + Copyright (c) 2007 John Tapsell + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This 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 +#include + +#include "ReniceDlg.moc" +#include +#include +#include "ui_ReniceDlgUi.h" +#include "processcore/process.h" + +ReniceDlg::ReniceDlg(QWidget* parent, const QStringList& processes, int currentCpuPrio, int currentCpuSched, int currentIoPrio, int currentIoSched ) + : KDialog( parent ) +{ + setObjectName( "Renice Dialog" ); + setModal( true ); + setCaption( i18n("Renice Process") ); + setButtons( Ok | Cancel ); + showButtonSeparator( true ); + previous_cpuscheduler = 0; + + connect( this, SIGNAL( okClicked() ), SLOT( slotOk() ) ); + + if(currentIoSched == KSysGuard::Process::None) { + // CurrentIoSched == 0 means that the priority is set automatically. + // Using the formula given by the linux kernel Documentation/block/ioprio + currentIoPrio = (currentCpuPrio+20)/5; + } + if(currentIoSched == (int)KSysGuard::Process::BestEffort && currentIoPrio == (currentCpuPrio+20)/5) { + // Unfortunately, in linux you can't ever set a process back to being None. So we fake it :) + currentIoSched = KSysGuard::Process::None; + } + ioniceSupported = (currentIoPrio != -2); + + + QWidget *widget = new QWidget(this); + setMainWidget(widget); + ui = new Ui_ReniceDlgUi(); + ui->setupUi(widget); + ui->listWidget->insertItems(0, processes); + + cpuScheduler = new QButtonGroup(this); + cpuScheduler->addButton(ui->radioNormal, (int)KSysGuard::Process::Other); + cpuScheduler->addButton(ui->radioBatch, (int)KSysGuard::Process::Batch); + cpuScheduler->addButton(ui->radioFIFO, (int)KSysGuard::Process::Fifo); + cpuScheduler->addButton(ui->radioRR, (int)KSysGuard::Process::RoundRobin); + if(currentCpuSched >= 0) { //negative means none of these + QAbstractButton *sched = cpuScheduler->button(currentCpuSched); + if(sched) { + sched->setChecked(true); //Check the current scheduler + previous_cpuscheduler = currentCpuSched; + } + } + cpuScheduler->setExclusive(true); + + ioScheduler = new QButtonGroup(this); + ioScheduler->addButton(ui->radioIONormal, (int)KSysGuard::Process::None); + ioScheduler->addButton(ui->radioIdle, (int)KSysGuard::Process::Idle); + ioScheduler->addButton(ui->radioRealTime, (int)KSysGuard::Process::RealTime); + ioScheduler->addButton(ui->radioBestEffort, (int)KSysGuard::Process::BestEffort); + if(currentIoSched >= 0) { //negative means none of these + QAbstractButton *iosched = ioScheduler->button(currentIoSched); + if(iosched) + iosched->setChecked(true); //Check the current io scheduler + } + + ioScheduler->setExclusive(true); + + if(ioniceSupported) + ui->sliderIO->setValue(currentIoPrio); + ui->sliderCPU->setValue(currentCpuPrio); + + ui->imgCPU->setPixmap( KIcon("cpu").pixmap(128, 128) ); + ui->imgIO->setPixmap( KIcon("drive-harddisk").pixmap(128, 128) ); + + newCPUPriority = 40; + + connect(cpuScheduler, SIGNAL(buttonClicked(int)), this, SLOT(cpuSchedulerChanged(int))); + connect(ioScheduler, SIGNAL(buttonClicked(int)), this, SLOT(updateUi())); + connect(ui->sliderCPU, SIGNAL(valueChanged(int)), this, SLOT(cpuSliderChanged(int))); + connect(ui->sliderIO, SIGNAL(valueChanged(int)), this, SLOT(ioSliderChanged(int))); + + updateUi(); +} + +void ReniceDlg::ioSliderChanged(int value) { + ui->sliderIO->setToolTip(QString::number(value)); +} + +void ReniceDlg::cpuSchedulerChanged(int value) { + if(value != previous_cpuscheduler) { + if( (value == (int)KSysGuard::Process::Other || value == KSysGuard::Process::Batch) && + (previous_cpuscheduler == (int)KSysGuard::Process::Fifo || previous_cpuscheduler == (int)KSysGuard::Process::RoundRobin)) { + int slider = -ui->sliderCPU->value() * 2 / 5 + 20; + setSliderRange(); + ui->sliderCPU->setValue( slider ); + } else if( (previous_cpuscheduler == (int)KSysGuard::Process::Other || previous_cpuscheduler == KSysGuard::Process::Batch) && + (value == (int)KSysGuard::Process::Fifo || value == (int)KSysGuard::Process::RoundRobin)) { + int slider = (-ui->sliderCPU->value() + 20) * 5 / 2; + setSliderRange(); + ui->sliderCPU->setValue( slider ); + } + } + previous_cpuscheduler = value; + updateUi(); +} + +void ReniceDlg::cpuSliderChanged(int value) { + if(cpuScheduler->checkedId() == (int)KSysGuard::Process::Other || cpuScheduler->checkedId() == (int)KSysGuard::Process::Batch) { + if( ioScheduler->checkedId() == -1 || ioScheduler->checkedId() == (int)KSysGuard::Process::None) { + //ionice is 'Normal', thus automatically calculated based on cpunice + ui->sliderIO->setValue((value+20)/5); + } + } + ui->sliderCPU->setToolTip(QString::number(value)); +} + +void ReniceDlg::updateUi() { + bool cpuPrioEnabled = ( cpuScheduler->checkedId() != -1); + bool ioPrioEnabled = ( ioniceSupported && ioScheduler->checkedId() != -1 && ioScheduler->checkedId() != (int)KSysGuard::Process::Idle && ioScheduler->checkedId() != (int)KSysGuard::Process::None); + + ui->sliderCPU->setEnabled(cpuPrioEnabled); + ui->lblCpuLow->setEnabled(cpuPrioEnabled); + ui->lblCpuHigh->setEnabled(cpuPrioEnabled); + + ui->sliderIO->setEnabled(ioPrioEnabled); + ui->lblIOLow->setEnabled(ioPrioEnabled); + ui->lblIOHigh->setEnabled(ioPrioEnabled); + + setSliderRange(); + cpuSliderChanged(ui->sliderCPU->value()); + ioSliderChanged(ui->sliderIO->value()); +} + +void ReniceDlg::setSliderRange() { + if(cpuScheduler->checkedId() == (int)KSysGuard::Process::Other || cpuScheduler->checkedId() == (int)KSysGuard::Process::Batch) { + //The slider is setting the priority, so goes from 19 to -20. We cannot actually do this with a slider, so instead we go from -19 to 20, and negate later + if(ui->sliderCPU->value() > 20) ui->sliderCPU->setValue(20); + ui->sliderCPU->setInvertedAppearance(true); + ui->sliderCPU->setMinimum(-19); + ui->sliderCPU->setMaximum(20); + ui->sliderCPU->setTickInterval(5); + } else { + if(ui->sliderCPU->value() < 1) ui->sliderCPU->setValue(1); + ui->sliderCPU->setInvertedAppearance(false); + ui->sliderCPU->setMinimum(1); + ui->sliderCPU->setMaximum(99); + ui->sliderCPU->setTickInterval(12); + } +} + +void ReniceDlg::slotOk() +{ + newCPUPriority = ui->sliderCPU->value(); + newIOPriority = ui->sliderIO->value(); + newCPUSched = cpuScheduler->checkedId(); + newIOSched = ioScheduler->checkedId(); +} diff --git a/ksysguard/processui/ReniceDlg.h b/ksysguard/processui/ReniceDlg.h new file mode 100644 index 000000000..fa445a53a --- /dev/null +++ b/ksysguard/processui/ReniceDlg.h @@ -0,0 +1,67 @@ +/* + KSysGuard, the KDE System Guard + + Copyright (c) 2006-2007 John Tapsell + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This 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 _ReniceDlg_h_ +#define _ReniceDlg_h_ + +#include + +class Ui_ReniceDlgUi; +class QButtonGroup; + +/** + * This class creates and handles a simple dialog to change the scheduling + * priority of a process. + */ +class ReniceDlg : public KDialog +{ + Q_OBJECT + +public: + /** Let the user specify the new priorities of the @p processes given, using the given current values. + * @p currentCpuSched The current Cpu Scheduler of the processes. Set to -1 to they have different schedulers + * @p currentIoSched The current I/O Scheduler of the processes. Set to -1 to they have different schedulers. Leave as the default -2 if not supported + */ + ReniceDlg(QWidget* parent, const QStringList& processes, int currentCpuPrio, int currentCpuSched, int currentIoPrio=-2, int currentIoSched=-2); + int newCPUPriority; + int newIOPriority; + int newCPUSched; + int newIOSched; + + bool ioniceSupported; + + +public Q_SLOTS: + void slotOk(); + void updateUi(); + void cpuSliderChanged(int value); + void ioSliderChanged(int value); + void cpuSchedulerChanged(int value); +private: + void setSliderRange(); + Ui_ReniceDlgUi *ui; + QButtonGroup *cpuScheduler; + QButtonGroup *ioScheduler; + int previous_cpuscheduler; +}; + +#endif diff --git a/ksysguard/processui/ReniceDlgUi.ui b/ksysguard/processui/ReniceDlgUi.ui new file mode 100644 index 000000000..ecc3ab790 --- /dev/null +++ b/ksysguard/processui/ReniceDlgUi.ui @@ -0,0 +1,443 @@ + + ReniceDlgUi + + + + 0 + 0 + 652 + 397 + + + + + 0 + + + 0 + + + + + Change scheduling priority for: + + + Qt::AlignVCenter + + + true + + + + + + + + 0 + 1 + + + + Qt::NoContextMenu + + + QAbstractItemView::NoSelection + + + true + + + + + + + + + + 128 + 128 + + + + + 128 + 128 + + + + + + + Qt::AutoText + + + + + + + + + + + + + 75 + true + + + + CPU Scheduler + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The standard time-sharing scheduler for processes without special requirements.</p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Normal Scheduling: Default Linux time-sharing (Other)</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-weight:600;">Normal<span style=" font-weight:400;"> is the standard Linux time-sharing scheduler that is intended for all processes that do not require special static priority real-time mechanisms. The process to run is chosen from the list of other</span> Normal<span style=" font-weight:400;"> or </span>Batch<span style=" font-weight:400;"> processes based on a dynamic priority that is determined only inside this list. The dynamic priority is based on the priority level given and increased for each time-quantum the process is ready to run, but denied to run by the scheduler. This ensures fair progress among all Normal processes.</span></p></body></html> + + + Normal + + + + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">For CPU-intensive non-interactive processes. Process is mildly disfavored in scheduling decisions.</p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Batch Scheduling</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-weight:600;"><span style=" font-weight:400; font-style:italic;">(Since Linux 2.6.16.)</span><span style=" font-weight:400;"> This policy is similar to </span>Normal<span style=" font-weight:400;">, except that this policy will cause the scheduler to always assume that the process is CPU-intensive. Consequently, the scheduler will apply a small scheduling penalty so that this process is mildly disfavored in scheduling decisions. This policy is useful for workloads that are non-interactive, but do not want to lower their nice value, and for workloads that want a deterministic scheduling policy without interactivity causing extra preemptions (between the workload's tasks).</span></p></body></html> + + + Batch + + + + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Process will run whenever runnable. Higher priority than Normal or Batch. Has Timeslicing.</p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Round Robin Scheduling</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Round Robin</span> is a simple enhancement of <span style=" font-weight:600;">FIFO</span>. Everything described below for <span style=" font-weight:600;">FIFO</span> also applies to <span style=" font-weight:600;">Round Robin</span>, except that each process is only allowed to run for a maximum time quantum.</p></body></html> + + + Round Robin + + + + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Process will run whenever runnable. Higher priority than Normal or Batch. No timeslicing.</p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">First In-First Out Scheduling</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">When a <span style=" font-weight:600;">FIFO</span> process becomes runnable, it will always immediately preempt any currently running <span style=" font-weight:600;">Normal</span> or <span style=" font-weight:600;">Batch</span> process.</p></body></html> + + + FIFO + + + + + + + + + Qt::Horizontal + + + QSizePolicy::MinimumExpanding + + + + 40 + 20 + + + + + + + + + 128 + 128 + + + + + 128 + 128 + + + + + + + + + + + + + + + + + 16777215 + 26 + + + + + 75 + true + + + + I/O Scheduler + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Process's priority is based on the CPU priority</p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Normal Scheduling</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">This is the same as <span style=" font-weight:600;">Best Effort</span> scheduling, except that the priority is calculated automatically based on the CPU priority. Processes with a higher priority will take priority for access to the hard disk. Programs running at the same <span style=" font-weight:600;">Best Effort/Normal</span> priority are served in a <span style=" font-weight:600;">Round Robin</span> fashion.</p></body></html> + + + Normal + + + + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Process can only use the hard disk when no other process has used it very recently.</p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Idle Scheduling</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">A program running with <span style=" font-weight:600;">Idle</span> I/O priority will only get disk time when no other program has asked for disk I/O for a defined grace period. The impact of <span style=" font-weight:600;">Idle</span> I/O processes on normal system activity should be zero. Priority is not applicable to this scheduling class.</p></body></html> + + + Idle + + + + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Process is given higher priority to access the hard disk than Normal.</p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Best Effort Scheduling</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Processes with a higher priority will take priority for access to the hard disk. Programs running at the same <span style=" font-weight:600;">Best Effort/Normal</span> priority are served in a <span style=" font-weight:600;">Round Robin</span> fashion.</p></body></html> + + + Best Effort + + + + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Process gets immediate access to the hard disk whenever needed, regardless of what else is going on.</p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Real Time Scheduling</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The <span style=" font-weight:600;">Real Time</span> scheduling class is given first access to the disk, regardless of what else is going on in the system. Thus the <span style=" font-weight:600;">Real Time</span> class needs to be used with some care, as it can starve other processes. As with the <span style=" font-weight:600;">Best Effort</span> class, 8 priority levels are defined denoting how big a time slice a given process will receive on each scheduling window</p></body></html> + + + Real Time + + + + + + + + + + + -19 + + + 20 + + + 0 + + + Qt::Horizontal + + + true + + + QSlider::TicksBelow + + + 5 + + + + + + + Low Priority + + + + + + + High Priority + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + Qt::Horizontal + + + QSizePolicy::MinimumExpanding + + + + 40 + 20 + + + + + + + + + + 7 + + + 1 + + + 3 + + + 3 + + + Qt::Horizontal + + + true + + + QSlider::TicksBelow + + + 1 + + + + + + + Low Priority + + + + + + + High Priority + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + + + listWidget + + + + diff --git a/ksysguard/processui/ksysguard.widgets b/ksysguard/processui/ksysguard.widgets new file mode 100644 index 000000000..aace7a5be --- /dev/null +++ b/ksysguard/processui/ksysguard.widgets @@ -0,0 +1,17 @@ +[Global] +PluginName=KSysGuardWidgets + + +[KSysGuardProcessList] +ToolTip=A list of processes (programs) running. +WhatsThis=A widget for showing all the processes running along with their memory usage and other details. +Group=KSysGuard (KDE) +ConstructorArgs=(parent) +IncludeFile=ksysguardprocesslist.h + +[KTextEditVT] +ToolTip=A text box suitable for displaying output from VT console-based programs. +WhatsThis=A widget for displaying out from console based programs. Some VT100 style commands are interpreted (For example to change the color) as well as some non-printable characters (backspace/delete etc will delete the last character.). For example the output from 'ls --color' can be displayed. +Group=KSysGuard (KDE) +ConstructorArgs=(parent) +IncludeFile=KTextEditVT.h diff --git a/ksysguard/processui/ksysguardprocesslist.cpp b/ksysguard/processui/ksysguardprocesslist.cpp new file mode 100644 index 000000000..9177d5664 --- /dev/null +++ b/ksysguard/processui/ksysguardprocesslist.cpp @@ -0,0 +1,1140 @@ +/* + KSysGuard, the KDE System Guard + + Copyright (c) 1999 - 2001 Chris Schlaeger + Copyright (c) 2006 - 2007 John Tapsell + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This 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-ksysguard.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include //For SIGTERM + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ksysguardprocesslist.moc" +#include "ksysguardprocesslist.h" +#include "ReniceDlg.h" +#include "ui_ProcessWidgetUI.h" + +#ifdef WITH_MONITOR_PROCESS_IO +#include "DisplayProcessDlg.h" +#endif + +#include +#include + +//Trolltech have a testing class for classes that inherit QAbstractItemModel. If you want to run with this run-time testing enabled, put the modeltest.* files in this directory and uncomment the next line +//#define DO_MODELCHECK +#ifdef DO_MODELCHECK +#include "modeltest.h" +#endif + +class ProgressBarItemDelegate : public QStyledItemDelegate +{ + public: + ProgressBarItemDelegate(QObject *parent) : QStyledItemDelegate(parent), startProgressColor(0x00, 0x71, 0xBC, 100), endProgressColor(0x83, 0xDD, 0xF5, 100), totalMemory(-1), numCpuCores(-1) {} + + virtual void paint(QPainter *painter, const QStyleOptionViewItem &opt, const QModelIndex &index) const + { + QStyleOptionViewItemV4 option = opt; + initStyleOption(&option,index); + + Q_ASSERT(index.model()); + QModelIndex realIndex = (reinterpret_cast< const QAbstractProxyModel *> (index.model()))->mapToSource(index); + KSysGuard::Process *process = reinterpret_cast< KSysGuard::Process * > (realIndex.internalPointer()); + Q_CHECK_PTR(process); + if(index.column() == ProcessModel::HeadingCPUUsage) { + if(numCpuCores == -1) + numCpuCores = index.data(ProcessModel::NumberOfProcessorsRole).toInt(); + percentage = (process->userUsage + process->sysUsage) / numCpuCores; + } else if(index.column() == ProcessModel::HeadingMemory) { + long long memory = 0; + if(process->vmURSS != -1) + memory = process->vmURSS; + else + memory = process->vmRSS; + if(totalMemory == -1) + totalMemory = index.data(ProcessModel::TotalMemoryRole).toLongLong(); + if(totalMemory > 0) + percentage = (int)(memory*100/totalMemory); + else + percentage = 0; + } else if(index.column() == ProcessModel::HeadingSharedMemory) { + if(process->vmURSS != -1) { + if(totalMemory == -1) + totalMemory = index.data(ProcessModel::TotalMemoryRole).toLongLong(); + if(totalMemory > 0) + percentage = (int)((process->vmRSS - process->vmURSS)*100/totalMemory); + else + percentage = 0; + } + } else + percentage = 0; + + if (percentage > 0) + drawPercentageDisplay(painter,option,index.data(Qt::DisplayRole).toString()); + else + QStyledItemDelegate::paint(painter, option, index); + } + + private: + void drawPercentageDisplay(QPainter *painter, const QStyleOptionViewItem& option, const QString& text) const + { + QApplication::style()->drawPrimitive(QStyle::PE_PanelItemViewItem,&option,painter); + + const QRect rect = option.rect; + if(percentage * rect.width() > 100 ) { //make sure the line will have a width of more than 1 pixel + QPen old = painter->pen(); + painter->setPen(Qt::NoPen); + QLinearGradient linearGrad( QPointF(rect.x(),rect.y()), QPointF(rect.x() + rect.width(), rect.y())); + linearGrad.setColorAt(0, startProgressColor); + linearGrad.setColorAt(1, endProgressColor); + painter->fillRect( rect.x(), rect.y(), rect.width() * percentage /100 , rect.height(), QBrush(linearGrad)); + painter->setPen( old ); + } + painter->drawText(rect,option.displayAlignment,text); + } + + mutable int percentage; + QColor startProgressColor; + QColor endProgressColor; + mutable long long totalMemory; + mutable int numCpuCores; +}; + +struct KSysGuardProcessListPrivate { + + KSysGuardProcessListPrivate(KSysGuardProcessList* q, const QString &hostName) + : mModel(q, hostName), mFilterModel(q), mUi(new Ui::ProcessWidget()), mProcessContextMenu(NULL), mUpdateTimer(NULL) + { + renice = new QAction(i18np("Renice Process...", "Renice Processes...", 1), q); + selectParent = new QAction(i18n("Jump to Parent Process"), q); + + selectTracer = new QAction(i18n("Jump to Process Debugging This One"), q); + window = new QAction(i18n("Show Application Window"), q); +#ifdef WITH_MONITOR_PROCESS_IO + monitorio = new QAction(i18n("Monitor Input && Output"), q); +#else + monitorio = 0; +#endif + resume = new QAction(i18n("Resume Stopped Process"), q); + kill = new QAction(i18np("Kill Process", "Kill Processes", 1), q); + kill->setIcon(KIcon("process-stop")); + + sigStop = new QAction(i18n("Suspend (STOP)"), q); + sigCont = new QAction(i18n("Continue (CONT)"), q); + sigHup = new QAction(i18n("Hangup (HUP)"), q); + sigInt = new QAction(i18n("Interrupt (INT)"), q); + sigTerm = new QAction(i18n("Terminate (TERM)"), q); + sigKill = new QAction(i18n("Kill (KILL)"), q); + sigUsr1 = new QAction(i18n("User 1 (USR1)"), q); + sigUsr2 = new QAction(i18n("User 2 (USR2)"), q); + } + + ~KSysGuardProcessListPrivate() { delete mUi; mUi = NULL; } + + /** The process model. This contains all the data on all the processes running on the system */ + ProcessModel mModel; + + /** The process filter. The mModel is connected to this, and this filter model connects to the view. This lets us + * sort the view and filter (by using the combo box or the search line) + */ + ProcessFilter mFilterModel; + + /** The graphical user interface for this process list widget, auto-generated by Qt Designer */ + Ui::ProcessWidget *mUi; + + /** The context menu when you right click on a process */ + QMenu *mProcessContextMenu; + + /** A timer to call updateList() every mUpdateIntervalMSecs */ + QTimer *mUpdateTimer; + + /** The time to wait, in milliseconds, between updating the process list */ + int mUpdateIntervalMSecs; + + QAction *renice; + QAction *kill; + QAction *selectParent; + QAction *selectTracer; + QAction *window; + QAction *monitorio; + QAction *resume; + QAction *sigStop; + QAction *sigCont; + QAction *sigHup; + QAction *sigInt; + QAction *sigTerm; + QAction *sigKill; + QAction *sigUsr1; + QAction *sigUsr2; +}; + +KSysGuardProcessList::KSysGuardProcessList(QWidget* parent, const QString &hostName) + : QWidget(parent), d(new KSysGuardProcessListPrivate(this, hostName)) +{ + d->mUpdateIntervalMSecs = 2000; //Set 2 seconds as the default update interval + d->mUi->setupUi(this); + d->mFilterModel.setSourceModel(&d->mModel); + d->mUi->treeView->setModel(&d->mFilterModel); +#ifdef DO_MODELCHECK + new ModelTest(&d->mModel, this); +#endif + d->mUi->treeView->setItemDelegate(new ProgressBarItemDelegate(d->mUi->treeView)); + + d->mUi->treeView->header()->setContextMenuPolicy(Qt::CustomContextMenu); + connect(d->mUi->treeView->header(), SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(showColumnContextMenu(const QPoint&))); + + d->mProcessContextMenu = new QMenu(d->mUi->treeView); + d->mUi->treeView->setContextMenuPolicy(Qt::CustomContextMenu); + connect(d->mUi->treeView, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(showProcessContextMenu(const QPoint&))); + + d->mUi->treeView->header()->setClickable(true); + d->mUi->treeView->header()->setSortIndicatorShown(true); + d->mUi->treeView->header()->setCascadingSectionResizes(true); + connect(d->mUi->btnKillProcess, SIGNAL(clicked()), this, SLOT(killSelectedProcesses())); + connect(d->mUi->txtFilter, SIGNAL(textChanged(const QString &)), this, SLOT(filterTextChanged(const QString &))); + connect(d->mUi->cmbFilter, SIGNAL(currentIndexChanged(int)), this, SLOT(setStateInt(int))); + connect(d->mUi->treeView, SIGNAL(expanded(const QModelIndex &)), this, SLOT(expandAllChildren(const QModelIndex &))); + connect(d->mUi->treeView->selectionModel(), SIGNAL(selectionChanged(const QItemSelection & , const QItemSelection & )), this, SLOT(selectionChanged())); + connect(&d->mFilterModel, SIGNAL(rowsInserted( const QModelIndex &, int, int)), this, SLOT(rowsInserted(const QModelIndex &, int, int))); + setMinimumSize(sizeHint()); + + /* Hide the vm size column by default since it's not very useful */ + d->mUi->treeView->header()->hideSection(ProcessModel::HeadingVmSize); + d->mUi->treeView->header()->hideSection(ProcessModel::HeadingNiceness); + d->mUi->treeView->header()->hideSection(ProcessModel::HeadingTty); + d->mUi->treeView->header()->hideSection(ProcessModel::HeadingCommand); + d->mUi->treeView->header()->hideSection(ProcessModel::HeadingPid); + d->mFilterModel.setFilterKeyColumn(0); + + d->mUi->treeView->header()->resizeSection(ProcessModel::HeadingCPUUsage, d->mUi->treeView->header()->sectionSizeHint(ProcessModel::HeadingCPUUsage)); + d->mUi->treeView->header()->resizeSection(ProcessModel::HeadingMemory, d->mUi->treeView->header()->sectionSizeHint(ProcessModel::HeadingMemory)); + d->mUi->treeView->header()->resizeSection(ProcessModel::HeadingSharedMemory, d->mUi->treeView->header()->sectionSizeHint(ProcessModel::HeadingSharedMemory)); + + //Process names can have mixed case. Make the filter case insensitive. + d->mFilterModel.setFilterCaseSensitivity(Qt::CaseInsensitive); + d->mFilterModel.setSortCaseSensitivity(Qt::CaseInsensitive); + + d->mUi->txtFilter->installEventFilter(this); + d->mUi->treeView->installEventFilter(this); + + //Logical column 0 will always be the tree bit with the process name. We expand this automatically in code, + //so don't let the user change it + d->mUi->treeView->header()->setResizeMode(0, QHeaderView::ResizeToContents); + d->mUi->treeView->header()->setStretchLastSection(true); + + //Sort by username by default + d->mUi->treeView->sortByColumn(ProcessModel::HeadingUser, Qt::AscendingOrder); + d->mFilterModel.sort(ProcessModel::HeadingUser, Qt::AscendingOrder); + + // Add all the actions to the main widget, and get all the actions to call actionTriggered when clicked + QSignalMapper *signalMapper = new QSignalMapper(this); + QList actions; + actions << d->renice << d->kill << d->selectParent << d->selectTracer << d->window; + if (d->monitorio) + actions << d->monitorio; + actions << d->resume << d->sigStop << d->sigCont << d->sigHup << d->sigInt << d->sigTerm << d->sigKill << d->sigUsr1 << d->sigUsr2; + foreach(QAction *action, actions) { + addAction(action); + connect(action, SIGNAL(triggered(bool)), signalMapper, SLOT(map())); + signalMapper->setMapping(action, action); + } + connect(signalMapper, SIGNAL(mapped(QObject *)), SLOT(actionTriggered(QObject *))); + + retranslateUi(); + + d->mFilterModel.setDynamicSortFilter(true); + + d->mUpdateTimer = new QTimer(this); + d->mUpdateTimer->setSingleShot(true); + connect(d->mUpdateTimer, SIGNAL(timeout()), this, SLOT(updateList())); + d->mUpdateTimer->start(d->mUpdateIntervalMSecs); + + d->mUi->btnKillProcess->setIcon(KIcon("process-stop")); + + //If the view resorts continually, then it can be hard to keep track of processes. By doing it only every few seconds it reduces the 'jumping around' + QTimer *mTimer = new QTimer(this); + connect(mTimer, SIGNAL(timeout()), &d->mFilterModel, SLOT(invalidate())); +// mTimer->start(4000); +// QT BUG? We have to disable the sorting for now because there seems to be a bug in Qt introduced in Qt 4.4beta which makes the view scroll back to the top + d->mModel.update(d->mUpdateIntervalMSecs); + +} + +KSysGuardProcessList::~KSysGuardProcessList() +{ + delete d; +} + +QTreeView *KSysGuardProcessList::treeView() const { + return d->mUi->treeView; +} + +QLineEdit *KSysGuardProcessList::filterLineEdit() const { + return d->mUi->txtFilter; +} + +ProcessFilter::State KSysGuardProcessList::state() const +{ + return d->mFilterModel.filter(); +} +void KSysGuardProcessList::setStateInt(int state) { + setState((ProcessFilter::State) state); + d->mUi->treeView->scrollTo( d->mUi->treeView->currentIndex()); +} +void KSysGuardProcessList::setState(ProcessFilter::State state) +{ //index is the item the user selected in the combo box + d->mFilterModel.setFilter(state); + d->mModel.setSimpleMode( (state != ProcessFilter::AllProcessesInTreeForm) ); + d->mUi->cmbFilter->setCurrentIndex( (int)state); + expandInit(); +} +void KSysGuardProcessList::filterTextChanged(const QString &newText) { + d->mFilterModel.setFilterRegExp(newText.trimmed()); + expandInit(); + d->mUi->btnKillProcess->setEnabled( d->mUi->treeView->selectionModel()->hasSelection() ); + d->mUi->treeView->scrollTo( d->mUi->treeView->currentIndex()); +} +void KSysGuardProcessList::selectionChanged() +{ + int numSelected = d->mUi->treeView->selectionModel()->selectedRows().size(); + d->mUi->btnKillProcess->setEnabled( numSelected != 0 ); + + d->renice->setText(i18np("Renice Process...", "Renice Processes...", numSelected)); + d->kill->setText(i18np("Kill Process", "Kill Processes", numSelected)); +} +void KSysGuardProcessList::showProcessContextMenu(const QModelIndex &index) { + if(!index.isValid()) return; + QRect rect = d->mUi->treeView->visualRect(index); + QPoint point(rect.x() + rect.width()/4, rect.y() + rect.height()/2 ); + showProcessContextMenu(point); +} +void KSysGuardProcessList::showProcessContextMenu(const QPoint &point) { + d->mProcessContextMenu->clear(); + + QModelIndexList selectedIndexes = d->mUi->treeView->selectionModel()->selectedRows(); + int numProcesses = selectedIndexes.size(); + + if(numProcesses == 0) return; //No processes selected, so no context menu + + QModelIndex realIndex = d->mFilterModel.mapToSource(selectedIndexes.at(0)); + KSysGuard::Process *process = reinterpret_cast (realIndex.internalPointer()); + + + + //If the selected process is a zombie, do not bother offering renice and kill options + bool showSignalingEntries = numProcesses != 1 || process->status != KSysGuard::Process::Zombie; + if(showSignalingEntries) { + d->mProcessContextMenu->addAction(d->renice); + QMenu *signalMenu = d->mProcessContextMenu->addMenu(i18n("Send Signal")); + signalMenu->addAction(d->sigStop); + signalMenu->addAction(d->sigCont); + signalMenu->addAction(d->sigHup); + signalMenu->addAction(d->sigInt); + signalMenu->addAction(d->sigTerm); + signalMenu->addAction(d->sigKill); + signalMenu->addAction(d->sigUsr1); + signalMenu->addAction(d->sigUsr2); + } + + if(numProcesses == 1 && process->parent_pid > 1) { + //As a design decision, I do not show the 'Jump to parent process' option when the + //parent is just 'init'. + + KSysGuard::Process *parent_process = d->mModel.getProcess(process->parent_pid); + if(parent_process) { //it should not be possible for this process to not exist, but check just incase + d->selectParent->setText(i18n("Jump to Parent Process (%1)", parent_process->name)); + d->mProcessContextMenu->addAction(d->selectParent); + } + } + + if(numProcesses == 1 && process->tracerpid > 0) { + //If the process is being debugged, offer to select it + d->mProcessContextMenu->addAction(d->selectTracer); + } + + if (numProcesses == 1 && !d->mModel.data(realIndex, ProcessModel::WindowIdRole).isNull()) { + d->mProcessContextMenu->addAction(d->window); + } + if (d->monitorio && numProcesses == 1 && d->mModel.isLocalhost() && (process->uid==0 || process->uid == getuid()) && process->pid != getpid() && process->pid != getppid()) { //Don't attach to ourselves - crashes + d->mProcessContextMenu->addAction(d->monitorio); + } + + if(numProcesses == 1 && process->status == KSysGuard::Process::Stopped) { + //If the process is being debugged, offer to select it + d->mProcessContextMenu->addAction(d->resume); + } + + if (showSignalingEntries) { + d->mProcessContextMenu->addSeparator(); + d->mProcessContextMenu->addAction(d->kill); + } + + d->mProcessContextMenu->popup(d->mUi->treeView->viewport()->mapToGlobal(point)); +} +void KSysGuardProcessList::actionTriggered(QObject *object) { + //Reset the text back to normal + d->selectParent->setText(i18n("Jump to Parent Process")); + QAction *result = dynamic_cast(object); + if(result == 0) { + //Escape was pressed. Do nothing. + } else if(result == d->renice) { + reniceSelectedProcesses(); + } else if(result == d->kill) { + killSelectedProcesses(); + } else if(result == d->selectParent) { + QModelIndexList selectedIndexes = d->mUi->treeView->selectionModel()->selectedRows(); + int numProcesses = selectedIndexes.size(); + if(numProcesses == 0) return; //No processes selected + QModelIndex realIndex = d->mFilterModel.mapToSource(selectedIndexes.at(0)); + KSysGuard::Process *process = reinterpret_cast (realIndex.internalPointer()); + if(process) + selectAndJumpToProcess(process->parent_pid); + } else if(result == d->selectTracer) { + QModelIndexList selectedIndexes = d->mUi->treeView->selectionModel()->selectedRows(); + int numProcesses = selectedIndexes.size(); + if(numProcesses == 0) return; //No processes selected + QModelIndex realIndex = d->mFilterModel.mapToSource(selectedIndexes.at(0)); + KSysGuard::Process *process = reinterpret_cast (realIndex.internalPointer()); + if(process) + selectAndJumpToProcess(process->tracerpid); + } else if(result == d->window) { + QModelIndexList selectedIndexes = d->mUi->treeView->selectionModel()->selectedRows(); + int numProcesses = selectedIndexes.size(); + if(numProcesses == 0) return; //No processes selected + foreach( const QModelIndex &index, selectedIndexes) { + QModelIndex realIndex = d->mFilterModel.mapToSource(index); + QVariant widVar= d->mModel.data(realIndex, ProcessModel::WindowIdRole); + if( !widVar.isNull() ) { + int wid = widVar.toInt(); + KWindowSystem::activateWindow(wid); + } + } +#ifdef WITH_MONITOR_PROCESS_IO + } else if(result == d->monitorio) { + QModelIndexList selectedIndexes = d->mUi->treeView->selectionModel()->selectedRows(); + if(selectedIndexes.isEmpty()) return; //No processes selected + QModelIndex realIndex = d->mFilterModel.mapToSource(selectedIndexes.at(0)); + KSysGuard::Process *process = reinterpret_cast (realIndex.internalPointer()); + if(process) { + DisplayProcessDlg *dialog = new DisplayProcessDlg( this,process ); + dialog->show(); + } +#endif + } else { + QList< long long > pidlist; + QModelIndexList selectedIndexes = d->mUi->treeView->selectionModel()->selectedRows(); + int numProcesses = selectedIndexes.size(); + if(numProcesses == 0) return; //No processes selected + foreach( const QModelIndex &index, selectedIndexes) { + QModelIndex realIndex = d->mFilterModel.mapToSource(index); + KSysGuard::Process *process = reinterpret_cast (realIndex.internalPointer()); + if(process) + pidlist << process->pid; + } + if(result == d->resume || result == d->sigCont) + killProcesses(pidlist, SIGCONT); //Despite the function name, this sends a signal, rather than kill it. Silly unix :) + else if(result == d->sigStop) + killProcesses(pidlist, SIGSTOP); + else if(result == d->sigHup) + killProcesses(pidlist, SIGHUP); + else if(result == d->sigInt) + killProcesses(pidlist, SIGINT); + else if(result == d->sigTerm) + killProcesses(pidlist, SIGTERM); + else if(result == d->sigKill) + killProcesses(pidlist, SIGKILL); + else if(result == d->sigUsr1) + killProcesses(pidlist, SIGUSR1); + else if(result == d->sigUsr2) + killProcesses(pidlist, SIGUSR2); + updateList(); + } +} + +void KSysGuardProcessList::selectAndJumpToProcess(int pid) { + KSysGuard::Process *process = d->mModel.getProcess(pid); + if(!process) return; + QModelIndex filterIndex = d->mFilterModel.mapFromSource( d->mModel.getQModelIndex(process, 0)); + d->mUi->treeView->clearSelection(); + d->mUi->treeView->setCurrentIndex(filterIndex); + d->mUi->treeView->scrollTo( filterIndex, QAbstractItemView::PositionAtCenter); + +} + +void KSysGuardProcessList::showColumnContextMenu(const QPoint &point){ + QMenu *menu = new QMenu(); + + QAction *action; + int index = d->mUi->treeView->header()->logicalIndexAt(point); + if(index >= 0) { + //selected a column. Give the option to hide it + action = new QAction(menu); + action->setData(-index-1); //We set data to be negative (and minus 1) to hide a column, and positive to show a column + action->setText(i18n("Hide Column '%1'", d->mFilterModel.headerData(index, Qt::Horizontal, Qt::DisplayRole).toString())); + menu->addAction(action); + if(d->mUi->treeView->header()->sectionsHidden()) { + menu->addSeparator(); + } + } + + + if(d->mUi->treeView->header()->sectionsHidden()) { + int num_headings = d->mFilterModel.columnCount(); + for(int i = 0; i < num_headings; ++i) { + if(d->mUi->treeView->header()->isSectionHidden(i)) { + action = new QAction(menu); + action->setText(i18n("Show Column '%1'", d->mFilterModel.headerData(i, Qt::Horizontal, Qt::DisplayRole).toString())); + action->setData(i); //We set data to be negative (and minus 1) to hide a column, and positive to show a column + menu->addAction(action); + } + } + } + QAction *actionKB = NULL; + QAction *actionMB = NULL; + QAction *actionGB = NULL; + + if( index == ProcessModel::HeadingVmSize || index == ProcessModel::HeadingMemory || index == ProcessModel::HeadingSharedMemory) { + //If the user right clicks on a column that contains a memory size, show a toggle option for displaying + //the memory in different units. e.g. "2000 k" or "2 m" + menu->addSeparator()->setText(i18n("Display Units")); + QActionGroup *unitsGroup = new QActionGroup(menu); + actionKB = new QAction(menu); + actionKB->setText(i18n("Kilobytes")); + actionKB->setCheckable(true); + menu->addAction(actionKB); + unitsGroup->addAction(actionKB); + actionMB = new QAction(menu); + actionMB->setText(i18n("Megabytes")); + actionMB->setCheckable(true); + menu->addAction(actionMB); + unitsGroup->addAction(actionMB); + actionGB = new QAction(menu); + actionGB->setText(i18n("Gigabytes")); + actionGB->setCheckable(true); + menu->addAction(actionGB); + unitsGroup->addAction(actionGB); + unitsGroup->setExclusive(true); + switch(d->mModel.units()) { + case ProcessModel::UnitsKB: + actionKB->setChecked(true); + break; + case ProcessModel::UnitsMB: + actionMB->setChecked(true); + break; + case ProcessModel::UnitsGB: + actionGB->setChecked(true); + break; + } + } + + + QAction *result = menu->exec(d->mUi->treeView->header()->mapToGlobal(point)); + if(!result) return; //Menu cancelled + if(result == actionKB) { + d->mModel.setUnits(ProcessModel::UnitsKB); + return; + } else if(result == actionMB) { + d->mModel.setUnits(ProcessModel::UnitsMB); + return; + } else if(result == actionGB) { + d->mModel.setUnits(ProcessModel::UnitsGB); + return; + } + int i = result->data().toInt(); + //We set data to be negative to hide a column, and positive to show a column + if(i < 0) + d->mUi->treeView->hideColumn(-1-i); + else { + d->mUi->treeView->showColumn(i); + d->mUi->treeView->resizeColumnToContents(i); + d->mUi->treeView->resizeColumnToContents(d->mFilterModel.columnCount()); + } + menu->deleteLater(); +} + +void KSysGuardProcessList::expandAllChildren(const QModelIndex &parent) +{ + //This is called when the user expands a node. This then expands all of its + //children. This will trigger this function again recursively. + QModelIndex sourceParent = d->mFilterModel.mapToSource(parent); + for(int i = 0; i < d->mModel.rowCount(sourceParent); i++) { + d->mUi->treeView->expand(d->mFilterModel.mapFromSource(d->mModel.index(i,0, sourceParent))); + } +} + +void KSysGuardProcessList::rowsInserted(const QModelIndex & parent, int start, int end ) +{ + if(d->mModel.isSimpleMode()) return; //No tree - no need to expand init + if(parent.isValid()) return; //Not a root node + //It is a root node that we just inserted - expand it + bool expanded = false; + for(int i = start; i <= end; i++) { + QModelIndex index = d->mFilterModel.index(i, 0, QModelIndex()); + if(!d->mUi->treeView->isExpanded(index)) { + if(!expanded) { + disconnect(d->mUi->treeView, SIGNAL(expanded(const QModelIndex &)), this, SLOT(expandAllChildren(const QModelIndex &))); + expanded = true; + } + d->mUi->treeView->expand(index); + } + } + if(expanded) + connect(d->mUi->treeView, SIGNAL(expanded(const QModelIndex &)), this, SLOT(expandAllChildren(const QModelIndex &))); +} +void KSysGuardProcessList::expandInit() +{ + if(d->mModel.isSimpleMode()) return; //No tree - no need to expand init + + bool expanded = false; + for(int i = 0; i < d->mFilterModel.rowCount(QModelIndex()); i++) { + QModelIndex index = d->mFilterModel.index(i, 0, QModelIndex()); + if(!d->mUi->treeView->isExpanded(index)) { + if(!expanded) { + disconnect(d->mUi->treeView, SIGNAL(expanded(const QModelIndex &)), this, SLOT(expandAllChildren(const QModelIndex &))); + expanded = true; + } + d->mUi->treeView->expand(index); + } + } + if(expanded) + connect(d->mUi->treeView, SIGNAL(expanded(const QModelIndex &)), this, SLOT(expandAllChildren(const QModelIndex &))); +} + +void KSysGuardProcessList::hideEvent ( QHideEvent * event ) //virtual protected from QWidget +{ + //Stop updating the process list if we are hidden + d->mUpdateTimer->stop(); + QWidget::hideEvent(event); +} + +void KSysGuardProcessList::showEvent ( QShowEvent * event ) //virtual protected from QWidget +{ + //Start updating the process list again if we are shown again + if(!d->mUpdateTimer->isActive()) { + d->mUpdateTimer->start(d->mUpdateIntervalMSecs); + } + + QWidget::showEvent(event); +} + +void KSysGuardProcessList::changeEvent( QEvent * event ) +{ + if (event->type() == QEvent::LanguageChange) { + d->mModel.retranslateUi(); + d->mUi->retranslateUi(this); + retranslateUi(); + } + QWidget::changeEvent(event); +} + +void KSysGuardProcessList::retranslateUi() +{ + d->mUi->cmbFilter->setItemIcon(ProcessFilter::AllProcesses, KIcon("view-process-all")); + d->mUi->cmbFilter->setItemIcon(ProcessFilter::AllProcessesInTreeForm, KIcon("view-process-all-tree")); + d->mUi->cmbFilter->setItemIcon(ProcessFilter::SystemProcesses, KIcon("view-process-system")); + d->mUi->cmbFilter->setItemIcon(ProcessFilter::UserProcesses, KIcon("view-process-users")); + d->mUi->cmbFilter->setItemIcon(ProcessFilter::OwnProcesses, KIcon("view-process-own")); + d->mUi->cmbFilter->setItemIcon(ProcessFilter::ProgramsOnly, KIcon("view-process-all")); +} + +void KSysGuardProcessList::updateList() +{ + if(isVisible()) { + d->mModel.update(d->mUpdateIntervalMSecs); + d->mUpdateTimer->start(d->mUpdateIntervalMSecs); + } +} + +int KSysGuardProcessList::updateIntervalMSecs() const +{ + return d->mUpdateIntervalMSecs; +} + +void KSysGuardProcessList::setUpdateIntervalMSecs(int intervalMSecs) +{ + d->mUpdateIntervalMSecs = intervalMSecs; + d->mUpdateTimer->setInterval(d->mUpdateIntervalMSecs); +} + +bool KSysGuardProcessList::reniceProcesses(const QList &pids, int niceValue) +{ + QList< long long> unreniced_pids; + for (int i = 0; i < pids.size(); ++i) { + bool success = d->mModel.processController()->setNiceness(pids.at(i), niceValue); + if(!success) { + unreniced_pids << pids.at(i); + } + } + if(unreniced_pids.isEmpty()) return true; //All processes were reniced successfully + if(!d->mModel.isLocalhost()) return false; //We can't use kdesu to renice non-localhost processes + + QStringList arguments; + arguments << "--attach" << QString::number(window()->winId()) << "--noignorebutton"; + arguments << "--" << "renice" << QString::number(niceValue); + + for (int i = 0; i < unreniced_pids.size(); ++i) { + arguments << QString::number(unreniced_pids.at(i)); + } + + QString su = KStandardDirs::findExe("kdesu"); //kdesu is a libexec program, so it will not be in the path. findExe will find it correctly anyway + if(su.isEmpty()) return false; //Cannot find kdesu + + QProcess *reniceProcess = new QProcess(NULL); + connect(reniceProcess, SIGNAL(error(QProcess::ProcessError)), this, SLOT(reniceFailed())); + connect(reniceProcess, SIGNAL(finished( int, QProcess::ExitStatus) ), this, SLOT(updateList())); + reniceProcess->start(su, arguments); + return true; //No way to tell if it was successful :( +} + +QList KSysGuardProcessList::selectedProcesses() const +{ + QList processes; + QModelIndexList selectedIndexes = d->mUi->treeView->selectionModel()->selectedRows(); + for(int i = 0; i < selectedIndexes.size(); ++i) { + KSysGuard::Process *process = reinterpret_cast (d->mFilterModel.mapToSource(selectedIndexes.at(i)).internalPointer()); + processes << process; + } + return processes; + +} + +void KSysGuardProcessList::reniceSelectedProcesses() +{ + QList processes = selectedProcesses(); + QStringList selectedAsStrings; + + if (processes.isEmpty()) + { + KMessageBox::sorry(this, i18n("You must select a process first.")); + return; + } + + int sched = -2; + int iosched = -2; + foreach(KSysGuard::Process *process, processes) { + selectedAsStrings << d->mModel.getStringForProcess(process); + if(sched == -2) sched = (int)process->scheduler; + else if(sched != -1 && sched != (int)process->scheduler) sched = -1; //If two processes have different schedulers, disable the cpu scheduler stuff + if(iosched == -2) iosched = (int)process->ioPriorityClass; + else if(iosched != -1 && iosched != (int)process->ioPriorityClass) iosched = -1; //If two processes have different schedulers, disable the cpu scheduler stuff + + } + + int firstPriority = processes.first()->niceLevel; + int firstIOPriority = processes.first()->ioniceLevel; + + bool supportsIoNice = d->mModel.processController()->supportsIoNiceness(); + if(!supportsIoNice) { iosched = -2; firstIOPriority = -2; } + ReniceDlg reniceDlg(d->mUi->treeView, selectedAsStrings, firstPriority, sched, firstIOPriority, iosched); + if(reniceDlg.exec() == QDialog::Rejected) return; + + QList renicePids; + QList changeCPUSchedulerPids; + QList changeIOSchedulerPids; + foreach(KSysGuard::Process *process, processes) { + switch(reniceDlg.newCPUSched) { + case -2: + case -1: //Invalid, not changed etc. + break; //So do nothing + case KSysGuard::Process::Other: + case KSysGuard::Process::Fifo: + if(reniceDlg.newCPUSched != (int)process->scheduler) { + changeCPUSchedulerPids << process->pid; + renicePids << process->pid; + } else if(reniceDlg.newCPUPriority != process->niceLevel) + renicePids << process->pid; + break; + + case KSysGuard::Process::RoundRobin: + case KSysGuard::Process::Batch: + if(reniceDlg.newCPUSched != (int)process->scheduler || reniceDlg.newCPUPriority != process->niceLevel) { + changeCPUSchedulerPids << process->pid; + } + break; + } + switch(reniceDlg.newIOSched) { + case -2: + case -1: //Invalid, not changed etc. + break; //So do nothing + case KSysGuard::Process::None: + if(reniceDlg.newIOSched != (int)process->ioPriorityClass) { + // Unfortunately linux doesn't actually let us set the ioniceness back to none after being set to something else + if(process->ioPriorityClass != KSysGuard::Process::BestEffort || reniceDlg.newIOPriority != process->ioniceLevel) + changeIOSchedulerPids << process->pid; + } + break; + case KSysGuard::Process::Idle: + if(reniceDlg.newIOSched != (int)process->ioPriorityClass) { + changeIOSchedulerPids << process->pid; + } + break; + case KSysGuard::Process::BestEffort: + if(process->ioPriorityClass == KSysGuard::Process::None && reniceDlg.newIOPriority == (process->niceLevel + 20)/5) + break; //Don't set to BestEffort if it's on None and the nicelevel wouldn't change + case KSysGuard::Process::RealTime: + if(reniceDlg.newIOSched != (int)process->ioPriorityClass || reniceDlg.newIOPriority != process->ioniceLevel) { + changeIOSchedulerPids << process->pid; + } + break; + } + + } + if(!changeCPUSchedulerPids.isEmpty()) { + Q_ASSERT(reniceDlg.newCPUSched >= 0); + if(!changeCpuScheduler(changeCPUSchedulerPids, (KSysGuard::Process::Scheduler) reniceDlg.newCPUSched, reniceDlg.newCPUPriority)) { + KMessageBox::sorry(this, i18n("You do not have sufficient privileges to change the CPU scheduler. Aborting.")); + return; + } + + } + if(!renicePids.isEmpty()) { + Q_ASSERT(reniceDlg.newCPUPriority <= 20 && reniceDlg.newCPUPriority >= -20); + if(!reniceProcesses(renicePids, reniceDlg.newCPUPriority)) { + KMessageBox::sorry(this, i18n("You do not have sufficient privileges to change the CPU priority. Aborting")); + return; + } + } + if(!changeIOSchedulerPids.isEmpty()) { + if(!changeIoScheduler(changeIOSchedulerPids, (KSysGuard::Process::IoPriorityClass) reniceDlg.newIOSched, reniceDlg.newIOPriority)) { + KMessageBox::sorry(this, i18n("You do not have sufficient privileges to change the IO scheduler and priority. Aborting")); + return; + } + } + updateList(); +} + +bool KSysGuardProcessList::changeIoScheduler(const QList< long long> &pids, KSysGuard::Process::IoPriorityClass newIoSched, int newIoSchedPriority) +{ + if(newIoSched == KSysGuard::Process::None) newIoSched = KSysGuard::Process::BestEffort; + if(newIoSched == KSysGuard::Process::Idle) newIoSchedPriority = 0; + QList< long long> unchanged_pids; + for (int i = 0; i < pids.size(); ++i) { + bool success = d->mModel.processController()->setIoNiceness(pids.at(i), newIoSched, newIoSchedPriority); + if(!success) { + unchanged_pids << pids.at(i); + } + } + if(unchanged_pids.isEmpty()) return true; + if(!d->mModel.isLocalhost()) return false; //We can't use kdesu to kill non-localhost processes + + + QString su = KStandardDirs::findExe("kdesu"); + if(su.isEmpty()) return false; //Cannot find kdesu + + //We must use kdesu to kill the process + + QStringList arguments; + arguments << "--attach" << QString::number(window()->winId()) << "--noignorebutton"; + if(unchanged_pids.size() == 1) { + arguments << "--" << "ionice" << "-p" << QString::number(unchanged_pids.at(0)) << "-c"; + switch(newIoSched) { + case KSysGuard::Process::Idle: + arguments << "3"; + break; + case KSysGuard::Process::BestEffort: + arguments << "2" << "-n" << QString::number(newIoSchedPriority); + break; + case KSysGuard::Process::RealTime: + arguments << "1" << "-n" << QString::number(newIoSchedPriority); + break; + default: + Q_ASSERT(false); + return false; //should never happen - wtf? + } + } else { + //Cope with multiple pids by doing a for loop + arguments << "--" << "sh" << "-c"; + QString sh("for f in "); + + for (int i = 0; i < unchanged_pids.size(); ++i) { + sh += QString::number(unchanged_pids.at(i)) + " "; + } + sh += "; do ionice -p \"$f\" "; + switch(newIoSched) { + case KSysGuard::Process::Idle: + sh += "-c 3"; + break; + case KSysGuard::Process::BestEffort: + sh += "-c 2 -n " + QString::number(newIoSchedPriority); + break; + case KSysGuard::Process::RealTime: + sh += "-c 1 -n " + QString::number(newIoSchedPriority); + break; + default: + Q_ASSERT(false); + return false; //should never happen - wtf? + } + sh += "; done"; + + arguments << sh; + } + + QProcess *process = new QProcess(NULL); + connect(process, SIGNAL(error(QProcess::ProcessError)), this, SLOT(ioniceFailed())); + connect(process, SIGNAL(finished( int, QProcess::ExitStatus) ), this, SLOT(updateList())); + process->start(su, arguments); + return true; //assume it ran successfully :( We cannot seem to actually check if it did. There must be a better solution +} + +bool KSysGuardProcessList::changeCpuScheduler(const QList< long long> &pids, KSysGuard::Process::Scheduler newCpuSched, int newCpuSchedPriority) +{ + if(newCpuSched == KSysGuard::Process::Other || newCpuSched == KSysGuard::Process::Batch) newCpuSchedPriority = 0; + QList< long long> unchanged_pids; + for (int i = 0; i < pids.size(); ++i) { + bool success = d->mModel.processController()->setScheduler(pids.at(i), newCpuSched, newCpuSchedPriority); + if(!success) { + unchanged_pids << pids.at(i); + } + } + if(unchanged_pids.isEmpty()) return true; + if(!d->mModel.isLocalhost()) { + KMessageBox::sorry(this, i18n("No.")); + return false; //We can't use kdesu to kill non-localhost processes + } + + QString su = KStandardDirs::findExe("kdesu"); + if(su.isEmpty()) { + KMessageBox::sorry(this, i18n("Could not find kdesu executable")); + return false; //Cannot find kdesu + } + QString setscheduler = KStandardDirs::findExe("setscheduler"); + if(setscheduler.isEmpty()) { + KMessageBox::sorry(this, i18n("Could not find setscheduler executable. This should have been installed alongside system monitor.")); + return false; + } + + //We must use kdesu to kill the process + + QStringList arguments; + arguments << "--attach" << QString::number(window()->winId()) << "--noignorebutton"; + if(unchanged_pids.size() == 1) { + arguments << "--" << setscheduler << QString::number(unchanged_pids.at(0)) << QString::number((int)newCpuSched) << QString::number(newCpuSchedPriority); + } else { + //Cope with multiple pids by doing a for loop + arguments << "--" << "sh" << "-c"; + QString sh("for f in "); + + for (int i = 0; i < unchanged_pids.size(); ++i) { + sh += QString::number(unchanged_pids.at(i)) + " "; + } + sh += "; do " + setscheduler + "\"$f\" " + newCpuSched + " " + newCpuSchedPriority; + sh += "; done"; + + arguments << sh; + } + + QProcess *process = new QProcess(NULL); + connect(process, SIGNAL(error(QProcess::ProcessError)), this, SLOT(ioniceFailed())); + connect(process, SIGNAL(finished( int, QProcess::ExitStatus) ), this, SLOT(updateList())); + process->start(su, arguments); + return true; //assume it ran successfully :( We cannot seem to actually check if it did. There must be a better solution +} + +bool KSysGuardProcessList::killProcesses(const QList< long long> &pids, int sig) +{ + QList< long long> unkilled_pids; + for (int i = 0; i < pids.size(); ++i) { + bool success = d->mModel.processController()->sendSignal(pids.at(i), sig); + if(!success) { + unkilled_pids << pids.at(i); + } + } + if(unkilled_pids.isEmpty()) return true; + if(!d->mModel.isLocalhost()) return false; //We can't use kdesu to kill non-localhost processes + + QString su = KStandardDirs::findExe("kdesu"); + if(su.isEmpty()) return false; //Cannot find kdesu + + kDebug() << "running " << su; + //We must use kdesu to kill the process + QStringList arguments; + arguments << "--attach" << QString::number(window()->winId()) << "--noignorebutton"; + arguments << "--" << "kill"; + if(sig != SIGTERM) { + arguments << ('-' + QString::number(sig)); + } + + for (int i = 0; i < unkilled_pids.size(); ++i) { + arguments << QString::number(unkilled_pids.at(i)); + } + + QProcess *killProcess = new QProcess(NULL); + connect(killProcess, SIGNAL(error(QProcess::ProcessError)), this, SLOT(killFailed())); + connect(killProcess, SIGNAL(finished( int, QProcess::ExitStatus) ), this, SLOT(updateList())); + killProcess->start(su, arguments); + return true; //assume it ran successfully :( We cannot seem to actually check if it did. There must be a better solution + +} +void KSysGuardProcessList::killSelectedProcesses() +{ + QModelIndexList selectedIndexes = d->mUi->treeView->selectionModel()->selectedRows(); + QStringList selectedAsStrings; + QList< long long> selectedPids; + + QList processes = selectedProcesses(); + foreach(KSysGuard::Process *process, processes) { + selectedPids << process->pid; + selectedAsStrings << d->mModel.getStringForProcess(process); + } + + if (selectedAsStrings.isEmpty()) + { + KMessageBox::sorry(this, i18n("You must select a process first.")); + return; + } + else + { + QString msg = i18np("Do you want to kill the selected process?", + "Do you want to kill the %1 selected processes?", + selectedAsStrings.count()); + + int res = KMessageBox::warningContinueCancelList(this, msg, selectedAsStrings, + i18n("Kill Process"), + KGuiItem(i18n("Kill")), + KStandardGuiItem::cancel(), + "killconfirmation"); + if (res != KMessageBox::Continue) + { + return; + } + } + + + Q_ASSERT(selectedPids.size() == selectedAsStrings.size()); + if(!killProcesses(selectedPids, SIGTERM)) return; + foreach(KSysGuard::Process *process, processes) { + process->timeKillWasSent.start(); + } + updateList(); +} + +void KSysGuardProcessList::reniceFailed() +{ + KMessageBox::sorry(this, i18n("You do not have the permission to renice the process and there " + "was a problem trying to run as root")); +} +void KSysGuardProcessList::killFailed() +{ + KMessageBox::sorry(this, i18n("You do not have the permission to kill the process and there " + "was a problem trying to run as root")); +} +void KSysGuardProcessList::ioniceFailed() +{ + KMessageBox::sorry(this, i18n("You do not have the permission to set the I/O priority and there " + "was a problem trying to run as root")); +} +bool KSysGuardProcessList::showTotals() const { + return d->mModel.showTotals(); +} + +void KSysGuardProcessList::setShowTotals(bool showTotals) //slot +{ + d->mModel.setShowTotals(showTotals); +} + +ProcessModel::Units KSysGuardProcessList::units() const { + return d->mModel.units(); +} + +void KSysGuardProcessList::setUnits(ProcessModel::Units unit) { + d->mModel.setUnits(unit); +} + +void KSysGuardProcessList::saveSettings(KConfigGroup &cg) { + /* Note that the ksysguard program does not use these functions. It saves the settings itself to an xml file instead */ + cg.writeEntry("units", (int)(units())); + cg.writeEntry("showTotals", showTotals()); + cg.writeEntry("filterState", (int)(state())); + cg.writeEntry("updateIntervalMSecs", updateIntervalMSecs()); + cg.writeEntry("headerState", d->mUi->treeView->header()->saveState()); + //If we change, say, the header between versions of ksysguard, then the old headerState settings will not be valid. + //The version property lets us keep track of which version we are + cg.writeEntry("version", PROCESSHEADERVERSION); +} + +void KSysGuardProcessList::loadSettings(const KConfigGroup &cg) { + /* Note that the ksysguard program does not use these functions. It saves the settings itself to an xml file instead */ + setUnits((ProcessModel::Units) cg.readEntry("units", (int)ProcessModel::UnitsKB)); + setShowTotals(cg.readEntry("showTotals", true)); + setStateInt(cg.readEntry("filterState", (int)ProcessFilter::AllProcesses)); + setUpdateIntervalMSecs(cg.readEntry("updateIntervalMSecs", 2000)); + int version = cg.readEntry("version", 0); + if(version == PROCESSHEADERVERSION) { //If the header has changed, the old settings are no longer valid. Only restore if version is the same + restoreHeaderState(cg.readEntry("headerState", QByteArray())); + } +} + +void KSysGuardProcessList::restoreHeaderState(const QByteArray & state) { + d->mUi->treeView->header()->restoreState(state); + d->mFilterModel.sort( d->mUi->treeView->header()->sortIndicatorSection(), d->mUi->treeView->header()->sortIndicatorOrder() ); +} + +bool KSysGuardProcessList::eventFilter(QObject *obj, QEvent *event) { + if (event->type() == QEvent::KeyPress) { + QKeyEvent *keyEvent = static_cast(event); + if(obj == d->mUi->treeView) { + if( keyEvent->key() == Qt::Key_Enter || keyEvent->key() == Qt::Key_Return) { + d->mUi->treeView->selectionModel()->select(d->mUi->treeView->currentIndex(), QItemSelectionModel::Select | QItemSelectionModel::Rows); + showProcessContextMenu(d->mUi->treeView->currentIndex()); + } + } else { + // obj must be txtFilter + if(keyEvent->matches(QKeySequence::MoveToNextLine) || keyEvent->matches(QKeySequence::SelectNextLine) || + keyEvent->matches(QKeySequence::MoveToPreviousLine) || keyEvent->matches(QKeySequence::SelectPreviousLine) || + keyEvent->matches(QKeySequence::MoveToNextPage) || keyEvent->matches(QKeySequence::SelectNextPage) || + keyEvent->matches(QKeySequence::MoveToPreviousPage) || keyEvent->matches(QKeySequence::SelectPreviousPage) || + keyEvent->key() == Qt::Key_Enter || keyEvent->key() == Qt::Key_Return) + { + QApplication::sendEvent(d->mUi->treeView, event); + return true; + } + } + } + return false; +} + +ProcessModel *KSysGuardProcessList::processModel() { + return &d->mModel; +} diff --git a/ksysguard/processui/ksysguardprocesslist.h b/ksysguard/processui/ksysguardprocesslist.h new file mode 100644 index 000000000..8f5118a5d --- /dev/null +++ b/ksysguard/processui/ksysguardprocesslist.h @@ -0,0 +1,202 @@ +/* + KSysGuard, the KDE System Guard + + Copyright (c) 1999, 2000 Chris Schlaeger + Copyright (c) 2006 John Tapsell + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This 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 _KSysGuardProcessList_h_ +#define _KSysGuardProcessList_h_ + +#include +#include +#include "ProcessModel.h" +#include "ProcessFilter.h" +#include "processes.h" + +class QShowEvent; +class QHideEvent; +class QLineEdit; +class QTreeView; +struct KSysGuardProcessListPrivate; +extern KApplication* Kapp; + +/** + * This widget implements a process list page. Besides the process + * list which is implemented as a ProcessList, it contains two + * comboxes and two buttons. The combo boxes are used to set the + * update rate and the process filter. The buttons are used to force + * an immediate update and to kill a process. + */ +class KDE_EXPORT KSysGuardProcessList : public QWidget +{ + Q_OBJECT + Q_PROPERTY( bool showTotalsInTree READ showTotals WRITE setShowTotals ) + Q_PROPERTY( ProcessFilter::State state READ state WRITE setState ) + Q_PROPERTY( int updateIntervalMSecs READ updateIntervalMSecs WRITE setUpdateIntervalMSecs ) + Q_PROPERTY( ProcessModel::Units units READ units WRITE setUnits ) + Q_ENUMS( ProcessFilter::State ) + Q_ENUMS( ProcessModel::Units ) + +public: + KSysGuardProcessList(QWidget* parent, const QString &hostName = QString()); + virtual ~KSysGuardProcessList(); + + QLineEdit *filterLineEdit() const; + QTreeView *treeView() const; + + /** Returns which processes we are currently filtering for and the way in which we show them. + * @see setState() + */ + ProcessFilter::State state() const; + + /** Returns the number of milliseconds that have to elapse before updating the list of processes */ + int updateIntervalMSecs() const; + + /** Whether the widget will show child totals for CPU and Memory etc usage */ + bool showTotals() const; + + /** The units to display memory sizes etc in. E.g. kb/mb/gb */ + ProcessModel::Units units() const; + + /** Returns a list of the processes that have been selected by the user. */ + QList selectedProcesses() const; + + /** Save the current state of the widget to the given config group + * + * @param[in] cg Config group to add these settings to + * */ + void saveSettings(KConfigGroup &cg); + + /** Load the saved state of the widget from the given config group */ + void loadSettings(const KConfigGroup &cg); + + /** Returns the process model used. Use with caution. */ + ProcessModel *processModel(); + + /** Restore the headings to the given state. */ + void restoreHeaderState(const QByteArray & state); + +public Q_SLOTS: + /** Inform the view that the user has changed the selection */ + void selectionChanged(); + + /** Send a kill signal to all the processes that the user has selected. Pops up a dialog box to confirm with the user */ + void killSelectedProcesses(); + + /** Send a signal to a list of given processes. + * @p pids A list of PIDs that should be sent the signal + * @p sig The signal to send. + * @return Whether the kill went ahead. True if successful or user cancelled. False if there was a problem + */ + bool killProcesses(const QList< long long> &pids, int sig); + + /** Renice all the processes that the user has selected. Pops up a dialog box to ask for the nice value and confirm */ + void reniceSelectedProcesses(); + + /** Change the CPU scheduler for the given of processes to the given scheduler, with the given scheduler priority. + * If the scheduler is Other or Batch, @p newCpuSchedPriority is ignored. + * @return Whether the cpu scheduler changing went ahead. True if successful or user cancelled. False if there was a problem + */ + bool changeCpuScheduler(const QList< long long> &pids, KSysGuard::Process::Scheduler newCpuSched, int newCpuSchedPriority); + + /** Change the I/O scheduler for the given of processes to the given scheduler, with the given scheduler priority. + * If the scheduler is Other or Batch, @p newCpuSchedPriority is ignored. + * @return Whether the cpu scheduler changing went ahead. True if successful or user cancelled. False if there was a problem + */ + bool changeIoScheduler(const QList< long long> &pids, KSysGuard::Process::IoPriorityClass newIoSched, int newIoSchedPriority); + /** Renice the processes given to the given niceValue. + * @return Whether the kill went ahead. True if successful or user cancelled. False if there was a problem + * */ + bool reniceProcesses(const QList &pids, int niceValue); + + /** Fetch new process information and redraw the display */ + void updateList(); + + /** Set which processes we are currently filtering for and the way in which we show them. */ + void setState(ProcessFilter::State state); + + /** Set the number of milliseconds that have to elapse before updating the list of processes */ + void setUpdateIntervalMSecs(int intervalMSecs); + + /** Set whether to show child totals for CPU and Memory etc usage */ + void setShowTotals(bool showTotals); + + /** Focus on a particular process, and select it */ + void selectAndJumpToProcess(int pid); + + /** The units to display memory sizes etc in. */ + void setUnits(ProcessModel::Units unit); + + /** Row was just inserted in the filter model */ + void rowsInserted ( const QModelIndex & parent, int start, int end ); + +private Q_SLOTS: + + /** Expand all the children, recursively, of the node given. Pass an empty QModelIndex to expand all the top level children */ + void expandAllChildren(const QModelIndex &parent); + + /** Expand init to show its children, but not the sub children processes. */ + void expandInit(); + + /** Display a context menu for the column headings allowing the user to show or hide columns. */ + void showColumnContextMenu(const QPoint &point); + + /** Display a context menu for the given process allowing the user to kill etc the process */ + void showProcessContextMenu(const QModelIndex &index); + /** Display a context menu for the selected processes allowing the user to kill etc the process */ + void showProcessContextMenu(const QPoint &point); + + /** Handle the situation where killing a process has failed - usually due to insufficent rights */ + void killFailed(); + + /** Handle the situation where renicing a process has failed - usually due to insufficent rights */ + void reniceFailed(); + + /** Handle the situation where ionice'ing a process has failed - usually due to insufficent rights */ + void ioniceFailed(); + + /** Set state from combo box int value */ + void setStateInt(int state); + + /** Called when the text in the gui filter text box has changed */ + void filterTextChanged(const QString &newText); + + /** Called when one of the actions (kill, renice etc) is clicked etc */ + void actionTriggered(QObject *object); +protected: + /** Inherit QWidget::showEvent(QShowEvent *) to enable the timer, for updates, when visible */ + virtual void showEvent(QShowEvent*); + + /** Inherit QWidget::hideEvent(QShowEvent *) to disable the timer, for updates, when not visible */ + virtual void hideEvent(QHideEvent*); + + /** Capture any change events sent to this widget. In particular QEvent::LanguageChange */ + virtual void changeEvent ( QEvent * event ); + + bool eventFilter(QObject *obj, QEvent *event); + + /** Retranslate the Ui as needed */ + void retranslateUi(); + +private: + KSysGuardProcessListPrivate* const d; +}; + +#endif diff --git a/ksysguard/tests/CMakeLists.txt b/ksysguard/tests/CMakeLists.txt new file mode 100644 index 000000000..51f41339d --- /dev/null +++ b/ksysguard/tests/CMakeLists.txt @@ -0,0 +1,12 @@ +set( EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR} ) + +include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/../ +${CMAKE_CURRENT_SOURCE_DIR}/../processcore/ ) + + +kde4_add_unit_test(processtest processtest.cpp) + +target_link_libraries(processtest processcore ${KDE4_KDECORE_LIBS} ${QT_QTTEST_LIBRARY}) + + + diff --git a/ksysguard/tests/guitest.cpp b/ksysguard/tests/guitest.cpp new file mode 100644 index 000000000..3940f93a4 --- /dev/null +++ b/ksysguard/tests/guitest.cpp @@ -0,0 +1,47 @@ +/* This file is part of the KDE project + Copyright (C) 2007 John Tapsell + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This 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 +#include + +#include +#include +#include + +#include + +#include "guitest.h" + +void testGuiProcess::testGUI() { + KSysGuardProcessList processlist(NULL); + + QTime t; + t.start(); + + for(int i =0; i < 10; i++) { + processlist.updateList(); + } + kDebug() << "time taken: " << t.elapsed() << "ms"; +} + +QTEST_KDEMAIN(testGuiProcess, GUI) + +#include "guitest.moc" + diff --git a/ksysguard/tests/guitest.h b/ksysguard/tests/guitest.h new file mode 100644 index 000000000..c9322afdb --- /dev/null +++ b/ksysguard/tests/guitest.h @@ -0,0 +1,32 @@ +/* This file is part of the KDE project + Copyright (C) 2007 John Tapsell + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This 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 GUITESTPROCESS_H +#define GUITESTPROCESS_H + +#include +class testGuiProcess: public QObject +{ + Q_OBJECT + private slots: + void testGUI(); +}; + +#endif + diff --git a/ksysguard/tests/processtest.cpp b/ksysguard/tests/processtest.cpp new file mode 100644 index 000000000..ab3d4042b --- /dev/null +++ b/ksysguard/tests/processtest.cpp @@ -0,0 +1,124 @@ +/* This file is part of the KDE project + Copyright (C) 2007 John Tapsell + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This 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 +#include + +#include +#include +#include + +#include "processcore/processes.h" +#include "processcore/process.h" + +#include "processtest.h" + +void testProcess::testProcesses() { + KSysGuard::Processes *processController = KSysGuard::Processes::getInstance(); + processController->updateAllProcesses(); + QList processes = processController->getAllProcesses(); + QSet pids; + foreach( KSysGuard::Process *process, processes) { + if(process->pid == 0) continue; + QVERIFY(process->pid > 0); + QVERIFY(!process->name.isEmpty()); + + //test all the pids are unique + QVERIFY(!pids.contains(process->pid)); + pids.insert(process->pid); + } + processController->updateAllProcesses(); + QList processes2 = processController->getAllProcesses(); + foreach( KSysGuard::Process *process, processes2) { + if(process->pid == 0) continue; + QVERIFY(process->pid > 0); + QVERIFY(!process->name.isEmpty()); + + //test all the pids are unique + if(!pids.contains(process->pid)) { + kDebug() << process->pid << " not found. " << process->name; + } + pids.remove(process->pid); + } + + QVERIFY(processes2.size() == processes.size()); + QCOMPARE(processes, processes2); //Make sure calling it twice gives the same results. The difference in time is so small that it really shouldn't have changed +} + + +unsigned long testProcess::countNumChildren(KSysGuard::Process *p) { + unsigned long total = p->children.size(); + for(int i =0; i < p->children.size(); i++) { + total += countNumChildren(p->children[i]); + } + return total; +} + +void testProcess::testProcessesTreeStructure() { + KSysGuard::Processes *processController = KSysGuard::Processes::getInstance(); + processController->updateAllProcesses(); + QList processes = processController->getAllProcesses(); + + foreach( KSysGuard::Process *process, processes) { + QCOMPARE(countNumChildren(process), process->numChildren); + + for(int i =0; i < process->children.size(); i++) { + QVERIFY(process->children[i]->parent); + QCOMPARE(process->children[i]->parent, process); + } + } + +} + +void testProcess::testProcessesModification() { + //We will modify the tree, then re-call getProcesses and make sure that it fixed everything we modified + KSysGuard::Processes *processController = KSysGuard::Processes::getInstance(); + processController->updateAllProcesses(); + KSysGuard::Process *initProcess = processController->getProcess(1); + + if(!initProcess || initProcess->numChildren < 3) + return; + + QVERIFY(initProcess); + QVERIFY(initProcess->children[0]); + QVERIFY(initProcess->children[1]); + kDebug() << initProcess->numChildren; + initProcess->children[0]->parent = initProcess->children[1]; + initProcess->children[1]->children.append(initProcess->children[0]); + initProcess->children[1]->numChildren++; + initProcess->numChildren--; + initProcess->children.removeAt(0); +} + +void testProcess::testTime() { + //See how long it takes to get proccess information + KSysGuard::Processes *processController = KSysGuard::Processes::getInstance(); + QTime t; + t.start(); + for(int i =0; i < 100; i++) + processController->updateAllProcesses(); + kDebug() << "Time elapsed: "<< t.elapsed() <<" ms, so " << t.elapsed()/100 << "ms" << endl; + QVERIFY(t.elapsed()/100 < 300); //It should take less than about 100ms. Anything longer than 300ms even on a slow system really needs to be optimised +} + +QTEST_KDEMAIN_CORE(testProcess) + +#include "processtest.moc" + diff --git a/ksysguard/tests/processtest.h b/ksysguard/tests/processtest.h new file mode 100644 index 000000000..eb41dbe5e --- /dev/null +++ b/ksysguard/tests/processtest.h @@ -0,0 +1,41 @@ +/* This file is part of the KDE project + Copyright (C) 2007 John Tapsell + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This 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 TESTPROCESS_H +#define TESTPROCESS_H + +#include +namespace KSysGuard +{ + class Process; +} +class testProcess: public QObject +{ + Q_OBJECT + private: + unsigned long countNumChildren(KSysGuard::Process *p); + private slots: + void testTime(); + void testProcesses(); + void testProcessesTreeStructure(); + void testProcessesModification(); +}; + +#endif + diff --git a/kworkspace/CMakeLists.txt b/kworkspace/CMakeLists.txt new file mode 100644 index 000000000..8c34c2272 --- /dev/null +++ b/kworkspace/CMakeLists.txt @@ -0,0 +1,28 @@ + + +set(kworkspace_LIB_SRCS kdisplaymanager.cpp + kworkspace.cpp + kwindowlistmenu.cpp + ) + +set(ksmserver_xml ${KDEBASE_WORKSPACE_SOURCE_DIR}/ksmserver/org.kde.KSMServerInterface.xml) +qt4_add_dbus_interface( kworkspace_LIB_SRCS ${ksmserver_xml} ksmserver_interface ) + +set(kwin_xml ${KDEBASE_WORKSPACE_SOURCE_DIR}/kwin/org.kde.KWin.xml) + +set_source_files_properties(${kwin_xml} PROPERTIES INCLUDE "interface_util.h") + +qt4_add_dbus_interface( kworkspace_LIB_SRCS ${kwin_xml} kwin_interface ) + + +kde4_add_library(kworkspace SHARED ${kworkspace_LIB_SRCS}) + +target_link_libraries(kworkspace ${KDE4_KDEUI_LIBS} ${X11_LIBRARIES} ) + +set_target_properties(kworkspace PROPERTIES VERSION ${GENERIC_LIB_VERSION} SOVERSION ${GENERIC_LIB_SOVERSION} ) +install(TARGETS kworkspace ${INSTALL_TARGETS_DEFAULT_ARGS} ) + +install( FILES kdisplaymanager.h + kworkspace.h + kwindowlistmenu.h + DESTINATION ${INCLUDE_INSTALL_DIR}/kworkspace COMPONENT Devel ) diff --git a/kworkspace/Mainpage.dox b/kworkspace/Mainpage.dox new file mode 100644 index 000000000..e8744f239 --- /dev/null +++ b/kworkspace/Mainpage.dox @@ -0,0 +1,21 @@ +/** @mainpage Workspace library + +libkworkspace provides functions to allow you to interact with the +%KDE session manager. + +@authors +Matthias Kalle Dalheimer \
    +Oswald Buddenhagen \
    +Matthias Elter \
    +Matthias Ettrich \ + +@maintainers +[Unknown/None] + +@licenses +@lgpl + +*/ + +// DOXYGEN_SET_PROJECT_NAME = libkworkspace +// vim:ts=4:sw=4:expandtab:filetype=doxygen diff --git a/kworkspace/Messages.sh b/kworkspace/Messages.sh new file mode 100644 index 000000000..2530fdde5 --- /dev/null +++ b/kworkspace/Messages.sh @@ -0,0 +1,2 @@ +#! /usr/bin/env bash +$XGETTEXT *.cpp -o $podir/libkworkspace.pot diff --git a/kworkspace/interface_util.h b/kworkspace/interface_util.h new file mode 100644 index 000000000..8a4fcd12c --- /dev/null +++ b/kworkspace/interface_util.h @@ -0,0 +1,26 @@ +/* This file is part of the KDE libraries + Copyright (C) 2008 Laurent Montel + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This 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 INTERFACEUTIL_H +#define INTERFACEUTIL_H + + +// needed by the DBUS interface +Q_DECLARE_METATYPE(QList) +#endif diff --git a/kworkspace/kdisplaymanager.cpp b/kworkspace/kdisplaymanager.cpp new file mode 100644 index 000000000..21168a78f --- /dev/null +++ b/kworkspace/kdisplaymanager.cpp @@ -0,0 +1,458 @@ +/* + Copyright (C) 2004 Oswald Buddenhagen + + This program is free software; you can redistribute it and/or + modify it under the terms of the Lesser GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the Lesser GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "kdisplaymanager.h" + +#ifdef Q_WS_X11 + +#include +#include +#include + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +static enum { Dunno, NoDM, NewKDM, OldKDM, GDM } DMType = Dunno; +static const char *ctl, *dpy; + +class KDisplayManager::Private +{ +public: + Private() : fd(-1) {} + ~Private() { + if (fd >= 0) + close( fd ); + } + + int fd; +}; + +KDisplayManager::KDisplayManager() : d(new Private) +{ + const char *ptr; + struct sockaddr_un sa; + + if (DMType == Dunno) { + if (!(dpy = ::getenv( "DISPLAY" ))) + DMType = NoDM; + else if ((ctl = ::getenv( "DM_CONTROL" ))) + DMType = NewKDM; + else if ((ctl = ::getenv( "XDM_MANAGED" )) && ctl[0] == '/') + DMType = OldKDM; + else if (::getenv( "GDMSESSION" )) + DMType = GDM; + else + DMType = NoDM; + } + switch (DMType) { + default: + return; + case NewKDM: + case GDM: + if ((d->fd = ::socket( PF_UNIX, SOCK_STREAM, 0 )) < 0) + return; + sa.sun_family = AF_UNIX; + if (DMType == GDM) { + strcpy( sa.sun_path, "/var/run/gdm_socket" ); + if (::connect( d->fd, (struct sockaddr *)&sa, sizeof(sa) )) { + strcpy( sa.sun_path, "/tmp/.gdm_socket" ); + if (::connect( d->fd, (struct sockaddr *)&sa, sizeof(sa) )) { + ::close( d->fd ); + d->fd = -1; + break; + } + } + GDMAuthenticate(); + } else { + if ((ptr = strchr( dpy, ':' ))) + ptr = strchr( ptr, '.' ); + snprintf( sa.sun_path, sizeof(sa.sun_path), + "%s/dmctl-%.*s/socket", + ctl, ptr ? int(ptr - dpy) : 512, dpy ); + if (::connect( d->fd, (struct sockaddr *)&sa, sizeof(sa) )) { + ::close( d->fd ); + d->fd = -1; + } + } + break; + case OldKDM: + { + QString tf( ctl ); + tf.truncate( tf.indexOf( ',' ) ); + d->fd = ::open( tf.toLatin1(), O_WRONLY ); + } + break; + } +} + +KDisplayManager::~KDisplayManager() +{ + delete d; +} + +bool +KDisplayManager::exec( const char *cmd ) +{ + QByteArray buf; + + return exec( cmd, buf ); +} + +/** + * Execute a KDM/GDM remote control command. + * @param cmd the command to execute. FIXME: undocumented yet. + * @param buf the result buffer. + * @return result: + * @li If true, the command was successfully executed. + * @p ret might contain addional results. + * @li If false and @p ret is empty, a communication error occurred + * (most probably KDM is not running). + * @li If false and @p ret is non-empty, it contains the error message + * from KDM. + */ +bool +KDisplayManager::exec( const char *cmd, QByteArray &buf ) +{ + bool ret = false; + int tl; + int len = 0; + + if (d->fd < 0) + goto busted; + + tl = strlen( cmd ); + if (::write( d->fd, cmd, tl ) != tl) { + bust: + ::close( d->fd ); + d->fd = -1; + busted: + buf.resize( 0 ); + return false; + } + if (DMType == OldKDM) { + buf.resize( 0 ); + return true; + } + for (;;) { + if (buf.size() < 128) + buf.resize( 128 ); + else if (buf.size() < len * 2) + buf.resize( len * 2 ); + if ((tl = ::read( d->fd, buf.data() + len, buf.size() - len)) <= 0) { + if (tl < 0 && errno == EINTR) + continue; + goto bust; + } + len += tl; + if (buf[len - 1] == '\n') { + buf[len - 1] = 0; + if (len > 2 && (buf[0] == 'o' || buf[0] == 'O') && + (buf[1] == 'k' || buf[1] == 'K') && buf[2] <= ' ') + ret = true; + break; + } + } + return ret; +} + +bool +KDisplayManager::canShutdown() +{ + if (DMType == OldKDM) + return strstr( ctl, ",maysd" ) != 0; + + QByteArray re; + + if (DMType == GDM) + return exec( "QUERY_LOGOUT_ACTION\n", re ) && re.indexOf( "HALT" ) >= 0; + + return exec( "caps\n", re ) && re.indexOf( "\tshutdown" ) >= 0; +} + +void +KDisplayManager::shutdown( KWorkSpace::ShutdownType shutdownType, + KWorkSpace::ShutdownMode shutdownMode, /* NOT Default */ + const QString &bootOption ) +{ + if (shutdownType == KWorkSpace::ShutdownTypeNone) + return; + + bool cap_ask; + if (DMType == NewKDM) { + QByteArray re; + cap_ask = exec( "caps\n", re ) && re.indexOf( "\tshutdown ask" ) >= 0; + } else { + if (!bootOption.isEmpty()) + return; + cap_ask = false; + } + if (!cap_ask && shutdownMode == KWorkSpace::ShutdownModeInteractive) + shutdownMode = KWorkSpace::ShutdownModeForceNow; + + QByteArray cmd; + if (DMType == GDM) { + cmd.append( shutdownMode == KWorkSpace::ShutdownModeForceNow ? + "SET_LOGOUT_ACTION " : "SET_SAFE_LOGOUT_ACTION " ); + cmd.append( shutdownType == KWorkSpace::ShutdownTypeReboot ? + "REBOOT\n" : "HALT\n" ); + } else { + cmd.append( "shutdown\t" ); + cmd.append( shutdownType == KWorkSpace::ShutdownTypeReboot ? + "reboot\t" : "halt\t" ); + if (!bootOption.isEmpty()) + cmd.append( "=" ).append( bootOption.toLocal8Bit() ).append( "\t" ); + cmd.append( shutdownMode == KWorkSpace::ShutdownModeInteractive ? + "ask\n" : + shutdownMode == KWorkSpace::ShutdownModeForceNow ? + "forcenow\n" : + shutdownMode == KWorkSpace::ShutdownModeTryNow ? + "trynow\n" : "schedule\n" ); + } + exec( cmd.data() ); +} + +bool +KDisplayManager::bootOptions( QStringList &opts, int &defopt, int ¤t ) +{ + if (DMType != NewKDM) + return false; + + QByteArray re; + if (!exec( "listbootoptions\n", re )) + return false; + + opts = QString::fromLocal8Bit( re.data() ).split( '\t', QString::SkipEmptyParts ); + if (opts.size() < 4) + return false; + + bool ok; + defopt = opts[2].toInt( &ok ); + if (!ok) + return false; + current = opts[3].toInt( &ok ); + if (!ok) + return false; + + opts = opts[1].split( ' ', QString::SkipEmptyParts ); + for (QStringList::Iterator it = opts.begin(); it != opts.end(); ++it) + (*it).replace( "\\s", " " ); + + return true; +} + +void +KDisplayManager::setLock( bool on ) +{ + if (DMType != GDM) + exec( on ? "lock\n" : "unlock\n" ); +} + +bool +KDisplayManager::isSwitchable() +{ + if (DMType == OldKDM) + return dpy[0] == ':'; + + if (DMType == GDM) + return exec( "QUERY_VT\n" ); + + QByteArray re; + + return exec( "caps\n", re ) && re.indexOf( "\tlocal" ) >= 0; +} + +int +KDisplayManager::numReserve() +{ + if (DMType == GDM) + return 1; /* Bleh */ + + if (DMType == OldKDM) + return strstr( ctl, ",rsvd" ) ? 1 : -1; + + QByteArray re; + int p; + + if (!(exec( "caps\n", re ) && (p = re.indexOf( "\treserve " )) >= 0)) + return -1; + return atoi( re.data() + p + 9 ); +} + +void +KDisplayManager::startReserve() +{ + if (DMType == GDM) + exec("FLEXI_XSERVER\n"); + else + exec("reserve\n"); +} + +bool +KDisplayManager::localSessions( SessList &list ) +{ + if (DMType == OldKDM) + return false; + + QByteArray re; + + if (DMType == GDM) { + if (!exec( "CONSOLE_SERVERS\n", re )) + return false; + QStringList sess = QString(re.data() +3).split( QChar(';'), QString::SkipEmptyParts); + for (QStringList::ConstIterator it = sess.begin(); it != sess.end(); ++it) { + QStringList ts = (*it).split( QChar(',') ); + SessEnt se; + se.display = ts[0]; + se.user = ts[1]; + se.vt = ts[2].toInt(); + se.session = ""; + se.self = ts[0] == ::getenv( "DISPLAY" ); /* Bleh */ + se.tty = false; + list.append( se ); + } + } else { + if (!exec( "list\talllocal\n", re )) + return false; + QStringList sess = QString(re.data() + 3).split(QChar('\t'), QString::SkipEmptyParts ); + for (QStringList::ConstIterator it = sess.begin(); it != sess.end(); ++it) { + QStringList ts = (*it).split( QChar(',') ); + SessEnt se; + se.display = ts[0]; + if (ts[1][0] == '@') + se.from = ts[1].mid( 1 ), se.vt = 0; + else + se.vt = ts[1].mid( 2 ).toInt(); + se.user = ts[2]; + se.session = ts[3]; + se.self = (ts[4].indexOf( '*' ) >= 0); + se.tty = (ts[4].indexOf( 't' ) >= 0); + list.append( se ); + } + } + return true; +} + +void +KDisplayManager::sess2Str2( const SessEnt &se, QString &user, QString &loc ) +{ + if (se.tty) { + user = i18nc("user: ...", "%1: TTY login", se.user ); + loc = se.vt ? QString("vt%1").arg( se.vt ) : se.display ; + } else { + user = + se.user.isEmpty() ? + se.session.isEmpty() ? + i18n("Unused") : + se.session == "" ? + i18n("X login on remote host") : + i18nc("... host", "X login on %1", se.session ) : + se.session == "" ? + se.user : + i18nc("user: session type", "%1: %2", + se.user, se.session ); + loc = + se.vt ? + QString("%1, vt%2").arg( se.display ).arg( se.vt ) : + se.display; + } +} + +QString +KDisplayManager::sess2Str( const SessEnt &se ) +{ + QString user, loc; + + sess2Str2( se, user, loc ); + return i18nc("session (location)", "%1 (%2)", user, loc ); +} + +bool +KDisplayManager::switchVT( int vt ) +{ + if (DMType == GDM) + return exec( QString("SET_VT %1\n").arg(vt).toLatin1() ); + + return exec( QString("activate\tvt%1\n").arg(vt).toLatin1() ); +} + +void +KDisplayManager::lockSwitchVT( int vt ) +{ + if (switchVT( vt )) + { + QDBusInterface screensaver("org.freedesktop.ScreenSaver", "/ScreenSaver", "org.freedesktop.ScreenSaver"); + screensaver.call( "Lock" ); + } +} + +void +KDisplayManager::GDMAuthenticate() +{ + FILE *fp; + const char *dpy, *dnum, *dne; + int dnl; + Xauth *xau; + + dpy = DisplayString( QX11Info::display() ); + if (!dpy) { + dpy = ::getenv( "DISPLAY" ); + if (!dpy) + return; + } + dnum = strchr( dpy, ':' ) + 1; + dne = strchr( dpy, '.' ); + dnl = dne ? dne - dnum : strlen( dnum ); + + /* XXX should do locking */ + if (!(fp = fopen( XauFileName(), "r" ))) + return; + + while ((xau = XauReadAuth( fp ))) { + if (xau->family == FamilyLocal && + xau->number_length == dnl && !memcmp( xau->number, dnum, dnl ) && + xau->data_length == 16 && + xau->name_length == 18 && !memcmp( xau->name, "MIT-MAGIC-COOKIE-1", 18 )) + { + QString cmd( "AUTH_LOCAL " ); + for (int i = 0; i < 16; i++) + cmd += QString::number( (uchar)xau->data[i], 16 ).rightJustified( 2, '0'); + cmd += '\n'; + if (exec( cmd.toLatin1() )) { + XauDisposeAuth( xau ); + break; + } + } + XauDisposeAuth( xau ); + } + + fclose (fp); +} + +#endif // Q_WS_X11 diff --git a/kworkspace/kdisplaymanager.h b/kworkspace/kdisplaymanager.h new file mode 100644 index 000000000..1610fec97 --- /dev/null +++ b/kworkspace/kdisplaymanager.h @@ -0,0 +1,102 @@ +/* + Copyright (C) 2004,2005 Oswald Buddenhagen + Copyright (C) 2005 Stephan Kulow + + This program is free software; you can redistribute it and/or + modify it under the terms of the Lesser GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the Lesser GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KDISPLAYMANAGER_H +#define KDISPLAYMANAGER_H + +#include "kworkspace.h" +#include +#include +#include +#include + +struct KDE_EXPORT SessEnt { + QString display, from, user, session; + int vt; + bool self:1, tty:1; +}; + +typedef QList SessList; + +class KDE_EXPORT KDisplayManager { + +#ifdef Q_WS_X11 + +public: + KDisplayManager(); + ~KDisplayManager(); + + bool canShutdown(); + void shutdown( KWorkSpace::ShutdownType shutdownType, + KWorkSpace::ShutdownMode shutdownMode, + const QString &bootOption = QString() ); + + void setLock( bool on ); + + bool isSwitchable(); + int numReserve(); + void startReserve(); + bool localSessions( SessList &list ); + bool switchVT( int vt ); + void lockSwitchVT( int vt ); + + bool bootOptions( QStringList &opts, int &dflt, int &curr ); + + static QString sess2Str( const SessEnt &se ); + static void sess2Str2( const SessEnt &se, QString &user, QString &loc ); + +private: + bool exec( const char *cmd, QByteArray &ret ); + bool exec( const char *cmd ); + + void GDMAuthenticate(); + +#else // Q_WS_X11 + +public: + KDisplayManager() {} + + bool canShutdown() { return false; } + void shutdown( KWorkSpace::ShutdownType shutdownType, + KWorkSpace::ShutdownMode shutdownMode, + const QString &bootOption = QString() ) {} + + void setLock( bool ) {} + + bool isSwitchable() { return false; } + int numReserve() { return -1; } + void startReserve() {} + bool localSessions( SessList &list ) { return false; } + void switchVT( int vt ) {} + + bool bootOptions( QStringList &opts, int &dflt, int &curr ); + +#endif // Q_WS_X11 + +private: +#ifdef Q_WS_X11 + class Private; + Private * const d; +#endif // Q_WS_X11 + +}; // class KDisplayManager + +#endif // KDISPLAYMANAGER_H + diff --git a/kworkspace/kwindowlistmenu.cpp b/kworkspace/kwindowlistmenu.cpp new file mode 100644 index 000000000..a5d322254 --- /dev/null +++ b/kworkspace/kwindowlistmenu.cpp @@ -0,0 +1,228 @@ +/***************************************************************** + +Copyright (c) 2000 Matthias Elter + Matthias Ettrich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************/ + +#include "kwindowlistmenu.h" + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#undef Bool +#include "kwindowlistmenu.moc" +#include "kwin_interface.h" + +static bool compareKWinWindowInfo( KWindowInfo* firstInfo, KWindowInfo* secondInfo ) +{ + QString firstTitle, secondTitle; + + if ( firstInfo ) + firstTitle = firstInfo->visibleNameWithState().toLower(); + + if ( secondInfo ) + secondTitle = secondInfo->visibleNameWithState().toLower(); + + return firstTitle.compare( secondTitle ) >= 0; +} + +class KWindowListMenu::Private +{ +}; + +KWindowListMenu::KWindowListMenu( QWidget *parent ) + : KMenu( parent ), d( new Private ) +{ +} + +KWindowListMenu::~KWindowListMenu() +{ + delete d; +} + +static bool standaloneDialog( const KWindowInfo* info, const QList& list ) +{ + WId group = info->groupLeader(); + + if ( group == 0 ) + return info->transientFor() == QX11Info::appRootWindow(); + + foreach ( KWindowInfo* info, list ) + if ( info->groupLeader() == group ) + return false; + + return true; +} + +void KWindowListMenu::init() +{ + int numberOfDesktops = KWindowSystem::numberOfDesktops(); + int currentDesktop = KWindowSystem::currentDesktop(); + WId activeWindow = KWindowSystem::activeWindow(); + + // Make sure the popup is not too wide, otherwise clicking in the middle of kdesktop + // wouldn't leave any place for the popup, and release would activate some menu entry. + int maxwidth = qApp->desktop()->screenGeometry( this ).width() / 2 - 100; + + clear(); + + QAction* unclutter = addAction( i18n("Unclutter Windows"), + this, SLOT( slotUnclutterWindows() ) ); + QAction* cascade = addAction( i18n("Cascade Windows"), + this, SLOT( slotCascadeWindows() ) ); + + // if we only have one desktop we won't be showing titles, so put a separator in + if ( numberOfDesktops == 1 ) + addSeparator(); + + QList windows; + foreach ( WId id, KWindowSystem::windows() ) + windows.append( KWindowSystem::windowInfo( id, NET::WMDesktop ) ); + + bool showAllDesktopsGroup = ( numberOfDesktops > 1 ); + + int i = 0; + for ( int j = 1; j <= numberOfDesktops + (showAllDesktopsGroup ? 1 : 0); j++ ) { + bool onAllDesktops = ( j > numberOfDesktops ); + int items = 0; + + // KDE4 porting - huh? didn't know you could set an item checked before it's created? + //if (!activeWindow && d == cd) + //setItemChecked(1000 + d, true); + + QList list; + + foreach (const KWindowInfo &wi, windows) { + if ( (wi.desktop() == j) || (onAllDesktops && wi.onAllDesktops()) + || (!showAllDesktopsGroup && wi.onAllDesktops()) ) { + list.append( new KWindowInfo( wi.win(), + NET::WMVisibleName | NET::WMState | NET::XAWMState | NET::WMWindowType, + NET::WM2GroupLeader | NET::WM2TransientFor ) ); + } + } + + qStableSort( list.begin(), list.end(), compareKWinWindowInfo ); + + foreach ( KWindowInfo* info, list ) { + ++i; + QString itemText = fontMetrics().elidedText(info->visibleNameWithState(), Qt::ElideMiddle, maxwidth); + + NET::WindowType windowType = info->windowType( NET::NormalMask | NET::DesktopMask + | NET::DockMask | NET::ToolbarMask | NET::MenuMask | NET::DialogMask + | NET::OverrideMask | NET::TopMenuMask | NET::UtilityMask | NET::SplashMask ); + + if ( (windowType == NET::Normal || windowType == NET::Unknown + || (windowType == NET::Dialog && standaloneDialog( info, list ))) + && !(info->state() & NET::SkipTaskbar) ) { + + QPixmap pm = KWindowSystem::icon( info->win(), 16, 16, true ); + items++; + + // ok, we have items on this desktop, let's show the title + if ( items == 1 && numberOfDesktops > 1 ) { + if( !onAllDesktops ) + addTitle( KWindowSystem::desktopName( j ) ); + else + addTitle( i18n( "On All Desktops" ) ); + } + + // Avoid creating unwanted accelerators. + itemText.replace( '&', QLatin1String( "&&" )); + + QAction* action = addAction( pm, itemText, this, SLOT( slotForceActiveWindow() ) ); + action->setData( (int)info->win() ); + + if ( info->win() == activeWindow ) + action->setChecked( true ); + } + } + + if ( j == currentDesktop ) { + unclutter->setEnabled( items > 0 ); + cascade->setEnabled( items > 0 ); + } + + qDeleteAll( list ); + } + + // no windows? + if ( i == 0 ) { + if ( numberOfDesktops > 1 ) + addSeparator(); // because we don't have any titles, nor a separator + + addAction( i18n( "No Windows" ) )->setEnabled( false ); + } +} + +void KWindowListMenu::slotForceActiveWindow() +{ + QAction* window = qobject_cast(sender()); + if (!window || !window->data().canConvert(QVariant::Int)) + return; + + KWindowSystem::forceActiveWindow(window->data().toInt()); +} + +void KWindowListMenu::slotSetCurrentDesktop() +{ + QAction* window = qobject_cast(sender()); + if (!window || !window->data().canConvert(QVariant::Int)) + return; + + KWindowSystem::setCurrentDesktop(window->data().toInt()); +} + +// This popup is much more useful from keyboard if it has the active +// window active by default - however, QPopupMenu tries hard to resist. +// QPopupMenu::popup() resets the active item, so this needs to be +// called after popup(). +void KWindowListMenu::selectActiveWindow() +{ + foreach (QAction* action, actions()) + if (action->isChecked()) { + setActiveAction(action); + break; + } +} + +void KWindowListMenu::slotUnclutterWindows() +{ + org::kde::KWin kwin("org.kde.kwin", "/KWin", QDBusConnection::sessionBus()); + kwin.unclutterDesktop(); +} + +void KWindowListMenu::slotCascadeWindows() +{ + org::kde::KWin kwin("org.kde.kwin", "/KWin", QDBusConnection::sessionBus()); + kwin.cascadeDesktop(); +} + diff --git a/kworkspace/kwindowlistmenu.h b/kworkspace/kwindowlistmenu.h new file mode 100644 index 000000000..2fe601be8 --- /dev/null +++ b/kworkspace/kwindowlistmenu.h @@ -0,0 +1,79 @@ +/***************************************************************** + +Copyright (c) 2000 Matthias Elter + Matthias Ettrich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************/ + +#ifndef KWINDOWLISTMENU_H +#define KWINDOWLISTMENU_H + +#include +#include + +/** + * This class provides a menu which contains actions + * to manage a window. It is used by the window manager + * for example an accessable there via the menu button of + * the window decoration. + */ +class KDE_EXPORT KWindowListMenu : public KMenu +{ + Q_OBJECT + + public: + /** + * Creates a new window list menu. + * + * @param parent The parent widget. + */ + explicit KWindowListMenu( QWidget *parent = 0 ); + + /** + * Destroys the window list menu. + */ + virtual ~KWindowListMenu(); + + /** + * Initializes the menu by filling it with actions + * for managing a window. + */ + void init(); + + public Q_SLOTS: + /** + * Pre-selects the active window in the popup menu, for faster + * keyboard navigation. Needs to be called after popup(). + * Should not be used when the popup is invoked using the mouse. + */ + void selectActiveWindow(); + + protected Q_SLOTS: + void slotForceActiveWindow(); + void slotSetCurrentDesktop(); + void slotUnclutterWindows(); + void slotCascadeWindows(); + + private: + class Private; + Private* const d; +}; + +#endif diff --git a/kworkspace/kworkspace.cpp b/kworkspace/kworkspace.cpp new file mode 100644 index 000000000..e66963d38 --- /dev/null +++ b/kworkspace/kworkspace.cpp @@ -0,0 +1,236 @@ +/* This file is part of the KDE libraries + Copyright (C) 1997 Matthias Kalle Dalheimer (kalle@kde.org) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This 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 "kworkspace.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include // getenv() +#include +#include +#include + +#ifdef Q_WS_X11 +#include +#include +#include +#include +#include +#endif + +#ifdef Q_WS_X11 +#define DISPLAY "DISPLAY" +#elif defined(Q_WS_QWS) +#define DISPLAY "QWS_DISPLAY" +#endif + +#include +#include +#include + +#include "kworkspace_p.h" + +namespace KWorkSpace +{ + +static void save_yourself_callback( SmcConn conn_P, SmPointer, int, Bool , int, Bool ) + { + SmcSaveYourselfDone( conn_P, True ); + } + +static void dummy_callback( SmcConn, SmPointer ) + { + } + +KRequestShutdownHelper::KRequestShutdownHelper() + { + SmcCallbacks calls; + calls.save_yourself.callback = save_yourself_callback; + calls.die.callback = dummy_callback; + calls.save_complete.callback = dummy_callback; + calls.shutdown_cancelled.callback = dummy_callback; + char* id = NULL; + char err[ 11 ]; + conn = SmcOpenConnection( NULL, NULL, 1, 0, + SmcSaveYourselfProcMask | SmcDieProcMask | SmcSaveCompleteProcMask + | SmcShutdownCancelledProcMask, &calls, NULL, &id, 10, err ); + if( id != NULL ) + free( id ); + if( conn == NULL ) + return; // no SM + // set the required properties, mostly dummy values + SmPropValue propvalue[ 5 ]; + SmProp props[ 5 ]; + propvalue[ 0 ].length = sizeof( int ); + int value0 = SmRestartNever; // so that this extra SM connection doesn't interfere + propvalue[ 0 ].value = &value0; + props[ 0 ].name = const_cast< char* >( SmRestartStyleHint ); + props[ 0 ].type = const_cast< char* >( SmCARD8 ); + props[ 0 ].num_vals = 1; + props[ 0 ].vals = &propvalue[ 0 ]; + struct passwd* entry = getpwuid( geteuid() ); + propvalue[ 1 ].length = entry != NULL ? strlen( entry->pw_name ) : 0; + propvalue[ 1 ].value = (SmPointer)( entry != NULL ? entry->pw_name : "" ); + props[ 1 ].name = const_cast< char* >( SmUserID ); + props[ 1 ].type = const_cast< char* >( SmARRAY8 ); + props[ 1 ].num_vals = 1; + props[ 1 ].vals = &propvalue[ 1 ]; + propvalue[ 2 ].length = 0; + propvalue[ 2 ].value = (SmPointer)( "" ); + props[ 2 ].name = const_cast< char* >( SmRestartCommand ); + props[ 2 ].type = const_cast< char* >( SmLISTofARRAY8 ); + props[ 2 ].num_vals = 1; + props[ 2 ].vals = &propvalue[ 2 ]; + propvalue[ 3 ].length = strlen( "requestshutdownhelper" ); + propvalue[ 3 ].value = (SmPointer)"requestshutdownhelper"; + props[ 3 ].name = const_cast< char* >( SmProgram ); + props[ 3 ].type = const_cast< char* >( SmARRAY8 ); + props[ 3 ].num_vals = 1; + props[ 3 ].vals = &propvalue[ 3 ]; + propvalue[ 4 ].length = 0; + propvalue[ 4 ].value = (SmPointer)( "" ); + props[ 4 ].name = const_cast< char* >( SmCloneCommand ); + props[ 4 ].type = const_cast< char* >( SmLISTofARRAY8 ); + props[ 4 ].num_vals = 1; + props[ 4 ].vals = &propvalue[ 4 ]; + SmProp* p[ 5 ] = { &props[ 0 ], &props[ 1 ], &props[ 2 ], &props[ 3 ], &props[ 4 ] }; + SmcSetProperties( conn, 5, p ); + notifier = new QSocketNotifier( IceConnectionNumber( SmcGetIceConnection( conn )), + QSocketNotifier::Read, this ); + connect( notifier, SIGNAL( activated( int )), SLOT( processData())); + } + +KRequestShutdownHelper::~KRequestShutdownHelper() + { + if( conn != NULL ) + { + delete notifier; + SmcCloseConnection( conn, 0, NULL ); + } + } + +void KRequestShutdownHelper::processData() + { + if( conn != NULL ) + IceProcessMessages( SmcGetIceConnection( conn ), 0, 0 ); + } + +bool KRequestShutdownHelper::requestShutdown( ShutdownConfirm confirm ) + { + if( conn == NULL ) + return false; + SmcRequestSaveYourself( conn, SmSaveBoth, True, SmInteractStyleAny, + confirm == ShutdownConfirmNo, True ); + // flush the request + IceFlush(SmcGetIceConnection(conn)); + return true; + } + +static KRequestShutdownHelper* helper = NULL; + +static void cleanup_sm() +{ + delete helper; +} + +bool requestShutDown( + ShutdownConfirm confirm, ShutdownType sdtype, ShutdownMode sdmode ) +{ + QApplication::syncX(); + kapp->updateRemoteUserTimestamp( "org.kde.ksmserver" ); + /* use ksmserver's dcop interface if necessary */ + if ( confirm == ShutdownConfirmYes || + sdtype != ShutdownTypeDefault || + sdmode != ShutdownModeDefault ) + { + org::kde::KSMServerInterface ksmserver("org.kde.ksmserver", "/KSMServer", QDBusConnection::sessionBus()); + QDBusReply reply = ksmserver.logout((int)confirm, (int)sdtype, (int)sdmode); + return (reply.isValid()); + } + if( helper == NULL ) + { + helper = new KRequestShutdownHelper(); + qAddPostRoutine(cleanup_sm); + } + return helper->requestShutdown( confirm ); +} + +bool canShutDown( ShutdownConfirm confirm, + ShutdownType sdtype, + ShutdownMode sdmode ) +{ + if ( confirm == ShutdownConfirmYes || + sdtype != ShutdownTypeDefault || + sdmode != ShutdownModeDefault ) + { + org::kde::KSMServerInterface ksmserver("org.kde.ksmserver", "/KSMServer", QDBusConnection::sessionBus()); + QDBusReply reply = ksmserver.canShutdown(); + if (!reply.isValid()) { + return false; + } + return reply; + } + + return true; +} + +static QTime smModificationTime; +void propagateSessionManager() +{ + QByteArray fName = QFile::encodeName(KStandardDirs::locateLocal("socket", "KSMserver")); + QString display = QString::fromLocal8Bit( ::getenv(DISPLAY) ); + // strip the screen number from the display + display.remove(QRegExp("\\.[0-9]+$")); + int i; + while( (i = display.indexOf(':')) >= 0) + display[i] = '_'; + + fName += '_'; + fName += display.toLocal8Bit(); + QByteArray smEnv = ::getenv("SESSION_MANAGER"); + bool check = smEnv.isEmpty(); + if ( !check && smModificationTime.isValid() ) { + QFileInfo info( fName ); + QTime current = info.lastModified().time(); + check = current > smModificationTime; + } + if ( check ) { + QFile f( fName ); + if ( !f.open( QIODevice::ReadOnly ) ) + return; + QFileInfo info ( f ); + smModificationTime = QTime( info.lastModified().time() ); + QTextStream t(&f); + t.setCodec( "ISO 8859-1" ); + QString s = t.readLine(); + f.close(); + ::setenv( "SESSION_MANAGER", s.toLatin1(), true ); + } +} + +} // end namespace + +#include "kworkspace_p.moc" diff --git a/kworkspace/kworkspace.h b/kworkspace/kworkspace.h new file mode 100644 index 000000000..7adad646d --- /dev/null +++ b/kworkspace/kworkspace.h @@ -0,0 +1,150 @@ +/* This file is part of the KDE libraries + Copyright (C) 1997 Matthias Kalle Dalheimer (kalle@kde.org) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This 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 KWORKSPACE_H +#define KWORKSPACE_H + +#include + +namespace KWorkSpace +{ + + /** + * The possible values for the @p confirm parameter of requestShutDown(). + */ + enum ShutdownConfirm { + /** + * Obey the user's confirmation setting. + */ + ShutdownConfirmDefault = -1, + /** + * Don't confirm, shutdown without asking. + */ + ShutdownConfirmNo = 0, + /** + * Always confirm, ask even if the user turned it off. + */ + ShutdownConfirmYes = 1 + }; + + /** + * The possible values for the @p sdtype parameter of requestShutDown(). + */ + enum ShutdownType { + /** + * Select previous action or the default if it's the first time. + */ + ShutdownTypeDefault = -1, + /** + * Only show log out dialog + */ + ShutdownTypeNone = 0, + /** + * Log out and reboot the machine. + */ + ShutdownTypeReboot = 1, + /** + * Log out and halt the machine. + */ + ShutdownTypeHalt = 2, + /** + * Only log out + */ + ShutdownTypeLogout = 3 + }; + + /** + * The possible values for the @p sdmode parameter of requestShutDown(). + */ + enum ShutdownMode { + /** + * Select previous mode or the default if it's the first time. + */ + ShutdownModeDefault = -1, + /** + * Schedule a shutdown (halt or reboot) for the time all active sessions + * have exited. + */ + ShutdownModeSchedule = 0, + /** + * Shut down, if no sessions are active. Otherwise do nothing. + */ + ShutdownModeTryNow = 1, + /** + * Force shutdown. Kill any possibly active sessions. + */ + ShutdownModeForceNow = 2, + /** + * Pop up a dialog asking the user what to do if sessions are still active. + */ + ShutdownModeInteractive = 3 + }; + + /** + * Asks the session manager to shut the session down. + * + * Using @p confirm == ShutdownConfirmYes or @p sdtype != ShutdownTypeDefault or + * @p sdmode != ShutdownModeDefault causes the use of ksmserver's DCOP + * interface. The remaining two combinations use the standard XSMP and + * will work with any session manager compliant with it. + * + * @param confirm Whether to ask the user if he really wants to log out. + * ShutdownConfirm + * @param sdtype The action to take after logging out. ShutdownType + * @param sdmode If/When the action should be taken. ShutdownMode + * @return true on success, false if the session manager could not be + * contacted. + */ + KDE_EXPORT bool requestShutDown( ShutdownConfirm confirm = ShutdownConfirmDefault, + ShutdownType sdtype = ShutdownTypeDefault, + ShutdownMode sdmode = ShutdownModeDefault ); + + /** + * Used to check whether a requestShutDown call with the same arguments + * has any chance of succeeding. + * + * For example, if KDE's own session manager cannot be contacted, we can't + * demand that the computer be shutdown, or force a confirmation dialog. + * + * Even if we can access the KDE session manager, the system or user + * configuration may prevent the user from requesting a shutdown or + * reboot. + */ + KDE_EXPORT bool canShutDown( ShutdownConfirm confirm = ShutdownConfirmDefault, + ShutdownType sdtype = ShutdownTypeDefault, + ShutdownMode sdmode = ShutdownModeDefault ); + + /** + * Propagates the network address of the session manager in the + * SESSION_MANAGER environment variable so that child processes can + * pick it up. + * + * If SESSION_MANAGER isn't defined yet, the address is searched in + * $HOME/.KSMserver. + * + * This function is called by clients that are started outside the + * session ( i.e. before ksmserver is started), but want to launch + * other processes that should participate in the session. Examples + * are kdesktop or kicker. + */ + KDE_EXPORT void propagateSessionManager(); + +} + +#endif diff --git a/kworkspace/kworkspace_p.h b/kworkspace/kworkspace_p.h new file mode 100644 index 000000000..b8ff7e924 --- /dev/null +++ b/kworkspace/kworkspace_p.h @@ -0,0 +1,49 @@ +/* This file is part of the KDE libraries + Copyright (C) 2007 Lubos Lunak + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This 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 KWORKSPACE_P_H +#define KWORKSPACE_P_H + +#include "kworkspace.h" + +class QSocketNotifier; + +namespace KWorkSpace +{ + +// A class that creates another connection to ksmserver and handles it properly. +class KRequestShutdownHelper + : public QObject + { + Q_OBJECT + public: + KRequestShutdownHelper(); + virtual ~KRequestShutdownHelper(); + bool requestShutdown( ShutdownConfirm confirm ); + private slots: + void processData(); + private: + SmcConn connection() const { return conn; } + QSocketNotifier* notifier; + SmcConn conn; + }; + +} + +#endif diff --git a/libplasmaclock/CMakeLists.txt b/libplasmaclock/CMakeLists.txt new file mode 100644 index 000000000..3269a4a68 --- /dev/null +++ b/libplasmaclock/CMakeLists.txt @@ -0,0 +1,23 @@ +project(libplasmaclock) + +set(plasmaclock_LIB_SRCS + clocknumber.cpp + clockapplet.cpp + calendar.cpp + calendartable.cpp + toolbutton.cpp +) + +kde4_add_ui_files(plasmaclock_LIB_SRCS calendar.ui timezonesConfig.ui) + +kde4_add_library(plasmaclock SHARED ${plasmaclock_LIB_SRCS}) + +target_link_libraries(plasmaclock plasma ${KDE4_KDEUI_LIBS}) + +set_target_properties(plasmaclock PROPERTIES VERSION ${GENERIC_LIB_VERSION} +SOVERSION ${GENERIC_LIB_SOVERSION} ) + +#clockapplet.h +install(FILES clocknumber.h clockapplet.h calendar.h calendartable.h plasmaclock_export.h +${CMAKE_CURRENT_BINARY_DIR}/ui_calendar.h DESTINATION ${INCLUDE_INSTALL_DIR}/libplasmaclock COMPONENT Devel) +install(TARGETS plasmaclock ${INSTALL_TARGETS_DEFAULT_ARGS} ) diff --git a/libplasmaclock/Messages.sh b/libplasmaclock/Messages.sh new file mode 100755 index 000000000..50de55ef7 --- /dev/null +++ b/libplasmaclock/Messages.sh @@ -0,0 +1,2 @@ +#! /usr/bin/env bash +$XGETTEXT *.cpp -o $podir/libplasmaclock.pot diff --git a/libplasmaclock/calendar.cpp b/libplasmaclock/calendar.cpp new file mode 100644 index 000000000..ae1dcbb8d --- /dev/null +++ b/libplasmaclock/calendar.cpp @@ -0,0 +1,206 @@ +/* + * Copyright 2008 Davide Bettio + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "calendar.h" + +//Qt +#include +#include +#include +#include +#include +#include + +//KDECore +#include +#include + +//Plasma +#include +#include +#include + +#include "toolbutton.h" + +namespace Plasma +{ + +class CalendarPrivate +{ + public: + ToolButton *back; + Plasma::Label *spacer0; + Plasma::Label *month; + #ifdef COOL_SPINBOX + SpinBox *year; + #else + Plasma::Label *year; + #endif + Plasma::Label *spacer1; + ToolButton *forward; + Plasma::CalendarTable *calendarTable; +}; + +//TODO +Calendar::Calendar(const QDate &, QGraphicsWidget *parent) + : QGraphicsWidget(parent), d(new CalendarPrivate()) +{ + +} + +Calendar::Calendar(QGraphicsWidget *parent) + : QGraphicsWidget(parent), d(new CalendarPrivate()) +{ + QGraphicsLinearLayout *m_layout = new QGraphicsLinearLayout(Qt::Vertical, this); + QGraphicsLinearLayout *m_hLayout = new QGraphicsLinearLayout(m_layout); + + d->calendarTable = new Plasma::CalendarTable(this); + d->calendarTable->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + connect(d->calendarTable, SIGNAL(displayedMonthChanged(int, int)), this, SLOT(displayedMonthChanged(int, int))); + + QGraphicsProxyWidget *backProxy = new QGraphicsProxyWidget(this); + d->back = new ToolButton(); + d->back->setText("<"); + d->back->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + connect(d->back, SIGNAL(clicked()), this, SLOT(prevMonth())); + backProxy->setWidget(d->back); + m_hLayout->addItem(backProxy); + + d->spacer0 = new Plasma::Label(this); + d->spacer0->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum); + m_hLayout->addItem(d->spacer0); + + d->month = new Plasma::Label(this); + d->month->setText(d->calendarTable->calendar()->monthName(d->calendarTable->calendar()->month(d->calendarTable->date()), d->calendarTable->calendar()->year(d->calendarTable->date()))); + d->month->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + m_hLayout->addItem(d->month); + + #ifdef COOL_SPINBOX + QGraphicsProxyWidget *yearProxy = new QGraphicsProxyWidget(this); + d->year = new SpinBox(); + d->year->setRange(d->calendarTable->calendar()->year(d->calendarTable->calendar()->earliestValidDate()), d->calendarTable->calendar()->year(d->calendarTable->calendar()->latestValidDate())); + d->year->setValue(d->calendarTable->calendar()->year(d->calendarTable->date())); + yearProxy->setWidget(d->year); + m_hLayout->addItem(yearProxy); + #else + d->year = new Plasma::Label; + d->year->setText(QString::number(d->calendarTable->calendar()->year(d->calendarTable->date()))); + d->year->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + m_hLayout->addItem(d->year); + #endif + + d->spacer1 = new Plasma::Label(this); + d->spacer1->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum); + m_hLayout->addItem(d->spacer1); + + QGraphicsProxyWidget *forwardProxy = new QGraphicsProxyWidget(this); + d->forward = new ToolButton(); + d->forward->setText(">"); + d->forward->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + connect(d->forward, SIGNAL(clicked()), this, SLOT(nextMonth())); + forwardProxy->setWidget(d->forward); + m_hLayout->addItem(forwardProxy); + + m_layout->addItem(m_hLayout); + + m_layout->addItem(d->calendarTable); +} + +Calendar::~Calendar() +{ + delete d; +} + +bool Calendar::setCalendar(KCalendarSystem *calendar) +{ + return d->calendarTable->setCalendar(calendar); +} + +bool Calendar::setDate(const QDate &date) +{ + return d->calendarTable->setDate(date); +} + +const QDate& Calendar::date() const +{ + return d->calendarTable->date(); +} + +void Calendar::displayedMonthChanged(int calendarSystemYear, int calendarSystemMonth) +{ + d->month->setText(d->calendarTable->calendar()->monthName(calendarSystemMonth, calendarSystemYear)); + + #ifdef COOL_SPINBOX + d->year->setValue(calendarSystemYear); + #else + d->year->setText(QString::number(calendarSystemYear)); + #endif +} + +void Calendar::prevMonth() +{ + QDate tmpDate = d->calendarTable->date(); + QDate newDate; + + int month = d->calendarTable->calendar()->month(tmpDate); + int year = d->calendarTable->calendar()->year(tmpDate); + + if (month == 1){ + month = 12; + year--; + }else{ + month--; + } + + if (d->calendarTable->calendar()->setYMD(newDate, year, month, d->calendarTable->calendar()->day(tmpDate))){ + d->calendarTable->setDate(newDate); + }else if (d->calendarTable->calendar()->setYMD(newDate, year, month, 1)){ + d->calendarTable->setDate(newDate); + } +} + +void Calendar::nextMonth() +{ + QDate tmpDate = d->calendarTable->date(); + QDate newDate; + + int month = d->calendarTable->calendar()->month(tmpDate); + int year = d->calendarTable->calendar()->year(tmpDate); + + if (month == 12){ + month = 1; + year++; + }else{ + month++; + } + + if (d->calendarTable->calendar()->setYMD(newDate, year, month, d->calendarTable->calendar()->day(tmpDate))){ + d->calendarTable->setDate(newDate); + }else if (d->calendarTable->calendar()->setYMD(newDate, year, month, 1)){ + d->calendarTable->setDate(newDate); + } +} + +CalendarTable *Calendar::calendarTable() const +{ + return d->calendarTable; +} +} + +#include "calendar.moc" diff --git a/libplasmaclock/calendar.h b/libplasmaclock/calendar.h new file mode 100644 index 000000000..3e07e7119 --- /dev/null +++ b/libplasmaclock/calendar.h @@ -0,0 +1,71 @@ +/* + * Copyright 2008 Davide Bettio + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef PLASMA_CALENDAR_H +#define PLASMA_CALENDAR_H + +#include + +#include "plasmaclock_export.h" + +#include + +#include "calendartable.h" + +namespace Plasma +{ + +class CalendarTable; +class CalendarPrivate; + +class PLASMACLOCK_EXPORT Calendar : public QGraphicsWidget +{ + Q_OBJECT + +public: + explicit Calendar(QGraphicsWidget *parent = 0); + Calendar(const QDate &, QGraphicsWidget *parent = 0); + ~Calendar(); + + const KCalendarSystem *calendar () const; + + bool setDate(const QDate &date); + const QDate& date() const; + + bool setCalendar(KCalendarSystem *calendar = 0); + + CalendarTable *calendarTable() const; + +Q_SIGNALS: + void dateChanged(const QDate &cur, const QDate &old); + void dateChanged(const QDate &date); + void tableClicked(); + +private Q_SLOTS: + void displayedMonthChanged(int calendarSystemYear, int calendarSystemMonth); + void prevMonth(); + void nextMonth(); + +private: + CalendarPrivate* const d; +}; + +} + +#endif diff --git a/libplasmaclock/calendar.ui b/libplasmaclock/calendar.ui new file mode 100644 index 000000000..0589c48c0 --- /dev/null +++ b/libplasmaclock/calendar.ui @@ -0,0 +1,42 @@ + + calendar + + + + 0 + 0 + 276 + 255 + + + + + + + + 0 + + + 0 + + + + + true + + + + + + + + KDatePicker + QFrame +
    kdatepicker.h
    +
    +
    + + + + +
    diff --git a/libplasmaclock/calendartable.cpp b/libplasmaclock/calendartable.cpp new file mode 100644 index 000000000..a7011353b --- /dev/null +++ b/libplasmaclock/calendartable.cpp @@ -0,0 +1,533 @@ +/* + * Copyright 2008 Davide Bettio + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "calendartable.h" + +//Qt +#include +#include +#include +#include +#include + +//KDECore +#include +#include + +//Plasma +#include +#include + +namespace Plasma +{ + +class CalendarCellBorder +{ +public: + CalendarCellBorder(int c, int w, int d, CalendarTable::CellTypes t, QDate dt) + : cell(c), + week(w), + weekDay(d), + type(t), + date(dt) + { + } + + int cell; + int week; + int weekDay; + CalendarTable::CellTypes type; + QDate date; +}; + +class CalendarTablePrivate +{ + public: + CalendarTablePrivate(CalendarTable *q, const QDate &cDate = QDate::currentDate()) + { + svg = new Svg(); + svg->setImagePath("widgets/calendar"); + svg->setContainsMultipleImages(true); + + calendar = KGlobal::locale()->calendar(); + + date = cDate; + + QDate currentDate = QDate::currentDate(); + month = calendar->month(currentDate); + year = calendar->year(currentDate); + + setupThemedElements(); + QObject::connect(Plasma::Theme::defaultTheme(), SIGNAL(themeChanged()), + q, SLOT(setupThemedElements())); + } + + ~CalendarTablePrivate() + { + delete svg; + } + + void setupThemedElements() + { + QColor c = Plasma::Theme::defaultTheme()->color(Plasma::Theme::HighlightColor); + c.setAlpha(180); + highlightBrush = QBrush(c); + } + + int firstMonthDayIndex(int y, int m) + { + QDate myDate; + calendar->setYMD(myDate, y, m, 1); + + return (((calendar->dayOfWeek(myDate) - 1) + (calendar->daysInWeek(date) - (calendar->weekStartDay() - 1))) % calendar->daysInWeek(date)) + 1; + } + + QRectF hoveredCellRect(CalendarTable *q, const QPointF &hoverPoint) + { + hoverDay = -1; + hoverWeek = -1; + + if (hoverPoint.isNull()) { + return QRectF(); + } + + if (hoverPoint.x() < centeringSpace + cellW + weekBarSpace) { + // skip the weekbar + return QRectF(); + } + + int x = (hoverPoint.x() - centeringSpace) / (cellW + cellSpace); + int y = (hoverPoint.y() - headerHeight - headerSpace) / (cellH + cellSpace); + + if (x < 1 || x > 7 || y < 0 || y > 5) { + return QRectF(); + } + + //FIXME: this should be a hint or something somewhere + hoverDay = x - 1; + hoverWeek = y; + //kDebug () << x << y; + return QRectF(q->cellX(x - 1) - glowRadius, q->cellY(y) - glowRadius, + cellW + glowRadius * 2, cellH + glowRadius * 2); + } + + void updateHoveredPainting(CalendarTable *q, const QPointF &hoverPoint) + { + QRectF newHoverRect = hoveredCellRect(q, hoverPoint); + + // now update what is needed, and only what is needed! + if (newHoverRect.isValid() && newHoverRect != hoverRect) { + if (hoverRect.isValid()) { + q->update(hoverRect); + } + q->update(newHoverRect); + } + + hoverRect = newHoverRect; + } + + int cell(int week, int weekDay, CalendarTable::CellTypes *type, QDate &cellDate) + { + QDate myDate; + + if ((week == 0) && (weekDay < firstMonthDayIndex(year, month))){ + int prevMonth = (month == 1) ? 12 : month - 1; + calendar->setYMD(myDate, year, prevMonth, 1); + + if (type) { + (*type) |= CalendarTable::NotInCurrentMonth; + } + + calendar->setYMD(cellDate, (prevMonth == 12) ? year - 1 : year, prevMonth, calendar->daysInMonth(myDate) - (firstMonthDayIndex(year, month) - 1 - weekDay)); + return calendar->daysInMonth(myDate) - (firstMonthDayIndex(year, month) - 1 - weekDay); + } else { + calendar->setYMD(myDate, year, month, 1); + int day = (week * calendar->daysInWeek(date) + weekDay) - firstMonthDayIndex(year, month) + 1; + + if (day <= calendar->daysInMonth(myDate)) { + if (type) { + (*type) &= ~CalendarTable::NotInCurrentMonth; + } + + calendar->setYMD(cellDate, year, month, day); + return day; + } else { + if (type) { + (*type) |= CalendarTable::NotInCurrentMonth; + } + int nextMonth = (month == 12) ? 1 : month + 1; + calendar->setYMD(cellDate, (nextMonth == 1) ? year + 1 : year, nextMonth, day - calendar->daysInMonth(myDate)); + return day - calendar->daysInMonth(myDate); + } + } + } + + Plasma::Svg *svg; + const KCalendarSystem *calendar; + QBrush highlightBrush; + QDate date; + QRectF hoverRect; + int month; + int year; + + int hoverWeek; + int hoverDay; + int centeringSpace; + int cellW; + int cellH; + int cellSpace; + int headerHeight; + int headerSpace; + int weekBarSpace; + int glowRadius; +}; + +CalendarTable::CalendarTable(const QDate &date, QGraphicsWidget *parent) + : QGraphicsWidget(parent), d(new CalendarTablePrivate(this, date)) +{ +} + +CalendarTable::CalendarTable(QGraphicsWidget *parent) + : QGraphicsWidget(parent), d(new CalendarTablePrivate(this)) +{ + setAcceptHoverEvents(true); +} + +CalendarTable::~CalendarTable() +{ + delete d; +} + +const KCalendarSystem *CalendarTable::calendar() const +{ + return d->calendar; +} + +bool CalendarTable::setCalendar(KCalendarSystem *calendar) +{ + d->calendar = calendar; + return false; +} + +bool CalendarTable::setDate(const QDate &date) +{ + int oldYear = d->year; + int oldMonth = d->month; + QDate oldDate = d->date; + d->date = date; + d->year = d->calendar->year(date); + d->month = d->calendar->month(date); + bool fullUpdate = false; + + if (oldYear != d->year){ + emit displayedYearChanged(d->year, d->month); + fullUpdate = true; + } + + if (oldMonth != d->month){ + emit displayedMonthChanged(d->year, d->month); + fullUpdate = true; + } + + d->updateHoveredPainting(this, QPointF()); + + if (fullUpdate) { + update(); + } else { + // only update the old and the new areas + int offset = d->firstMonthDayIndex(d->year, d->month); + int daysInWeek = d->calendar->daysInWeek(d->date); + + int day = d->calendar->day(oldDate); + int x = ((offset + day - 1) % daysInWeek); + if (x == 0) { + x = daysInWeek; + } + int y = (offset + day - 2) / daysInWeek; + update(cellX(x - 1) - d->glowRadius, cellY(y) - d->glowRadius, + d->cellW + d->glowRadius * 2, d->cellH + d->glowRadius * 2); + + day = d->calendar->day(date); + x = (offset + day - 1) % daysInWeek; + if (x == 0) { + x = daysInWeek; + } + y = (offset + day - 2) / daysInWeek; + update(cellX(x - 1) - d->glowRadius, cellY(y) - d->glowRadius, + d->cellW + d->glowRadius * 2, d->cellH + d->glowRadius * 2); + } + + return false; +} + +const QDate& CalendarTable::date() const +{ + return d->date; +} + +int CalendarTable::cellX(int weekDay) +{ + return boundingRect().x() + d->centeringSpace + + d->weekBarSpace + d->cellW + + ((d->cellW + d->cellSpace) * (weekDay)); +} + +int CalendarTable::cellY(int week) +{ + return (int) boundingRect().y() + (d->cellW + d->cellSpace) * (week) + d->headerHeight + d->headerSpace; +} + +void CalendarTable::wheelEvent(QGraphicsSceneWheelEvent * event) +{ + Q_UNUSED(event); + + if (event->delta() < 0) { + if (d->month == 12) { + d->month = 1; + d->year++; + emit displayedYearChanged(d->year, d->month); + } else { + d->month++; + } + + emit displayedMonthChanged(d->year, d->month); + } else if (event->delta() > 0) { + if (d->month == 1) { + d->month = 12; + d->year--; + emit displayedYearChanged(d->year, d->month); + } else { + d->month--; + } + + emit displayedMonthChanged(d->year, d->month); + } + + update(); +} + +void CalendarTable::mousePressEvent(QGraphicsSceneMouseEvent *event) +{ + event->accept(); + + if ((event->pos().x() >= cellX(0)) && (event->pos().x() <= cellX(d->calendar->daysInWeek(d->date)) - d->cellSpace) && + (event->pos().y() >= cellY(0)) && (event->pos().y() <= cellY(5) - d->cellSpace)){ + + int week = -1; + int weekDay = -1; + QDate cellDate; + + for (int i = 0; i < d->calendar->daysInWeek(d->date); i++) { + if ((event->pos().x() >= cellX(i)) && (event->pos().x() <= cellX(i + 1) - d->cellSpace)) + weekDay = i; + } + + for (int i = 0; i < 5; i++) { + if ((event->pos().y() >= cellY(i)) && (event->pos().y() <= cellY(i + 1) - d->cellSpace)) + week = i; + } + + if ((week >= 0) && (weekDay >= 0)) { + d->hoverDay = -1; + d->hoverWeek = -1; + QDate tmpDate; + QDate oldDate = d->date; + d->cell(week, weekDay + 1, 0, tmpDate); + + if (tmpDate == oldDate) { + return; + } + + setDate(tmpDate); + emit dateChanged(tmpDate, oldDate); + emit dateChanged(tmpDate); + } + } +} + +void CalendarTable::mouseMoveEvent(QGraphicsSceneMouseEvent *event) +{ + mousePressEvent(event); +} + +void CalendarTable::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) +{ + Q_UNUSED(event); + + emit tableClicked(); +} + +void CalendarTable::hoverMoveEvent(QGraphicsSceneHoverEvent *event) +{ + d->updateHoveredPainting(this, event->pos()); +} + +void CalendarTable::resizeEvent(QGraphicsSceneResizeEvent * event) +{ + Q_UNUSED(event); + + QRectF r = contentsRect(); + int rectSize = int(qMin(r.width() / 8, r.height() / 6)); + + //Using integers to help to keep things aligned to the grid + //kDebug() << r.width() << rectSize; + d->cellSpace = qMax(1, qMin(4, rectSize / 20)); + d->headerSpace = d->cellSpace * 2; + d->weekBarSpace = d->cellSpace * 2 + 1; + d->cellH = rectSize - d->cellSpace; + d->cellW = rectSize - d->cellSpace; + d->glowRadius = d->cellW * .1; + d->headerHeight = (int) (d->cellH / 1.5); + d->centeringSpace = qMax(0, int((r.width() - (rectSize * 8) - (d->cellSpace * 7)) / 2)); +} + +void CalendarTable::paintCell(QPainter *p, int cell, int week, int weekDay, CellTypes type, const QDate &cellDate) +{ + QString cellSuffix = cellSVGSuffix(cell, week, weekDay, type & NotInCurrentMonth, cellDate); + d->svg->paint(p, QRectF(cellX(weekDay), cellY(week), d->cellW, d->cellH), cellSuffix); +} + +void CalendarTable::paintBorder(QPainter *p, int cell, int week, int weekDay, CellTypes type, const QDate &cellDate) +{ + Q_UNUSED(cell); + Q_UNUSED(cellDate); + + if (type & Hovered) { + p->fillRect(QRect(cellX(weekDay), cellY(week), d->cellW, d->cellH), d->highlightBrush); + } + + QString elementId; + + if (type & Today) { + elementId = "today"; + } else if (type & Selected) { + elementId = "selected"; + } else { + return; + } + + d->svg->paint(p, QRectF(cellX(weekDay) - 1, cellY(week) - 1, + d->cellW + 1, d->cellH + 2), + elementId); +} + +QString CalendarTable::cellSVGSuffix(int cell, int week, int weekDay, CellTypes type, const QDate &cellDate) +{ + Q_UNUSED(week); + Q_UNUSED(weekDay); + Q_UNUSED(cellDate); + return QString::number(cell) + (type & NotInCurrentMonth ? "-grayed" : ""); +} + +void CalendarTable::paint(QPainter *p, const QStyleOptionGraphicsItem *option, QWidget *widget) +{ + Q_UNUSED(widget); + int daysInWeek = d->calendar->daysInWeek(d->date); + + // Draw weeks numbers column and day header + QRectF r = boundingRect(); + d->svg->paint(p, QRectF(r.x() + d->centeringSpace, cellY(0), d->cellW, + cellY(5) - cellY(0) - d->cellSpace), "weeksColumn"); + d->svg->paint(p, QRectF(r.x() + d->centeringSpace, r.y(), + cellX(daysInWeek) - r.x() - d->cellSpace - d->centeringSpace, d->headerHeight), "weekDayHeader"); + + QList borders; + QList hovers; + QDate currentDate = QDate::currentDate(); //FIXME: calendar timezone + + //kDebug() << "exposed: " << option->exposedRect; + for (int week = 0; week < 5; week++) { + for (int weekDay = 0; weekDay < daysInWeek; weekDay++) { + + int x = cellX(weekDay); + int y = cellY(week); + + QRectF cellRect(x, y, d->cellW, d->cellH); + if (!cellRect.intersects(option->exposedRect)) { + continue; + } + + QDate cellDate(d->date.year(), d->date.month(), (week * 7) + (weekDay + 1)); + CalendarTable::CellTypes type(CalendarTable::NoType); + // get cell info + int cell = d->cell(week, weekDay + 1, &type, cellDate); + + // check what kind of cell we are + if (cellDate == currentDate) { + type |= Today; + } + + if (cellDate == d->date) { + type |= Selected; + } + + if (type != CalendarTable::NoType && type != CalendarTable::NotInCurrentMonth) { + borders.append(CalendarCellBorder(cell, week, weekDay, type, cellDate)); + } + + if (week == d->hoverWeek && weekDay == d->hoverDay) { + type |= Hovered; + hovers.append(CalendarCellBorder(cell, week, weekDay, type, cellDate)); + } + + paintCell(p, cell, week, weekDay, type, cellDate); + + if (weekDay == 0) { + QRectF cellRect(r.x() + d->centeringSpace, y, d->cellW, d->cellH); + d->svg->paint(p, cellRect, "week" + QString::number(d->calendar->weekNumber(cellDate))); + } + } + } + + // Draw days + if (option->exposedRect.intersects(QRect(r.x(), r.y(), r.width(), d->headerHeight))) { + p->setPen(Plasma::Theme::defaultTheme()->color(Plasma::Theme::TextColor)); + int weekStartDay = d->calendar->weekStartDay(); + for (int i = 0; i < daysInWeek; i++){ + int weekDay = ((i + weekStartDay - 1) % daysInWeek) + 1; + QString dayName = d->calendar->weekDayName(weekDay, KCalendarSystem::ShortDayName); + p->drawText(QRectF(cellX(i), r.y(), d->cellW, d->headerHeight), Qt::AlignCenter, dayName); + } + } + + // Draw hovers + foreach (const CalendarCellBorder &border, hovers) { + p->save(); + paintBorder(p, border.cell, border.week, border.weekDay, border.type, border.date); + p->restore(); + } + + // Draw borders + foreach (const CalendarCellBorder &border, borders) { + p->save(); + paintBorder(p, border.cell, border.week, border.weekDay, border.type, border.date); + p->restore(); + } + + /* + p->save(); + p->setPen(Qt::red); + p->drawRect(option->exposedRect.adjusted(1, 1, -2, -2)); + p->restore(); + */ +} + +} //namespace Plasma + +#include "calendartable.moc" diff --git a/libplasmaclock/calendartable.h b/libplasmaclock/calendartable.h new file mode 100644 index 000000000..06e629edd --- /dev/null +++ b/libplasmaclock/calendartable.h @@ -0,0 +1,90 @@ +/* + * Copyright 2008 Davide Bettio + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef PLASMA_CALENDARWIDGET_H +#define PLASMA_CALENDARWIDGET_H + +#include + +#include "plasmaclock_export.h" + +#include + +namespace Plasma +{ + +class CalendarTablePrivate; + +class PLASMACLOCK_EXPORT CalendarTable : public QGraphicsWidget +{ + Q_OBJECT + +public: + enum CellType { NoType = 0, + Today = 1, + Selected = 2, + Hovered = 4, + NotInCurrentMonth = 8 }; + Q_DECLARE_FLAGS(CellTypes, CellType) + + explicit CalendarTable(QGraphicsWidget *parent = 0); + CalendarTable(const QDate &, QGraphicsWidget *parent = 0); + ~CalendarTable(); + + const KCalendarSystem *calendar () const; + + bool setDate(const QDate &date); + const QDate& date() const; + + bool setCalendar(KCalendarSystem *calendar = 0); + +Q_SIGNALS: + void dateChanged(const QDate &cur, const QDate &old); + void dateChanged(const QDate &date); + void tableClicked(); + void displayedMonthChanged(int calendarSystemYear, int calendarSystemMonth); + void displayedYearChanged(int calendarSystemYear, int calendarSystemMonth); + +protected: + int cellX(int weekDay); + int cellY(int week); + + void paint(QPainter *p, const QStyleOptionGraphicsItem *option, QWidget *widget = 0); + void wheelEvent(QGraphicsSceneWheelEvent *event); + void mousePressEvent(QGraphicsSceneMouseEvent *event); + void mouseMoveEvent(QGraphicsSceneMouseEvent *event); + void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); + void hoverMoveEvent(QGraphicsSceneHoverEvent *event); + void resizeEvent(QGraphicsSceneResizeEvent * event); + + virtual void paintCell(QPainter *p, int cell, int week, int weekDay, CellTypes type, const QDate &cellDate); + virtual void paintBorder(QPainter *p, int cell, int week, int weekDay, CellTypes type, const QDate &cellDate); + virtual QString cellSVGSuffix(int cell, int week, int weekDay, CellTypes type, const QDate &cellDate); + +private: + Q_PRIVATE_SLOT(d, void setupThemedElements()) + + friend class CalendarTablePrivate; + CalendarTablePrivate* const d; +}; + +} + +Q_DECLARE_OPERATORS_FOR_FLAGS(Plasma::CalendarTable::CellTypes) +#endif diff --git a/libplasmaclock/clockapplet.cpp b/libplasmaclock/clockapplet.cpp new file mode 100644 index 000000000..dd3977289 --- /dev/null +++ b/libplasmaclock/clockapplet.cpp @@ -0,0 +1,379 @@ +/*************************************************************************** + * Copyright (C) 2007-2008 by Riccardo Iaconelli * + * Copyright (C) 2007-2008 by Sebastian Kuegler * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * + ***************************************************************************/ + +#include "clockapplet.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "calendar.h" + +#include "ui_timezonesConfig.h" + +class ClockApplet::Private +{ +public: + Private() + : timezone(ClockApplet::localTimezone()) + {} + + Ui::timezonesConfig ui; + QString timezone; + QPoint clicked; + QStringList selectedTimezones; + QString prettyTimezone; + + void addTzToTipText(QString &subText, QString tz) + { + Plasma::Applet applet; + Plasma::DataEngine::Data data = applet.dataEngine("time")->query(tz); + if (tz == "UTC") { + subText += "
    UTC "; + } + else { + subText += "
    " + data["Timezone City"].toString().replace("_", " ")+" "; + } + subText += KGlobal::locale()->formatTime(data["Time"].toTime(), false) + ", "; + subText += KGlobal::locale()->formatDate(data["Date"].toDate()); + } +}; + +ClockApplet::ClockApplet(QObject *parent, const QVariantList &args) + : Plasma::PopupApplet(parent, args), + d(new Private) +{ + setPopupIcon(QIcon()); +} + +ClockApplet::~ClockApplet() +{ + delete d; +} + +void ClockApplet::toolTipAboutToShow() +{ + updateContent(); +} + +void ClockApplet::toolTipHidden() +{ + Plasma::ToolTipManager::self()->clearContent(this); +} + +void ClockApplet::updateContent() +{ + Plasma::ToolTipContent tipData; + + { + // the main text contains the current timezone's time and date + Plasma::DataEngine::Data data = dataEngine("time")->query(currentTimezone()); + QString mainText = d->prettyTimezone + " "; + mainText += KGlobal::locale()->formatTime(data["Time"].toTime(), false) + "
    "; + mainText += KGlobal::locale()->formatDate(data["Date"].toDate()); + tipData.setMainText(mainText); + } + + QString subText; + if (!isLocalTimezone()) { + d->addTzToTipText(subText, localTimezone()); + } + + foreach (const QString &tz, getSelectedTimezones()) { + if (tz == currentTimezone()) { + continue; + } + d->addTzToTipText(subText, tz); + } + + tipData.setSubText(subText); + + // query for custom content + Plasma::ToolTipContent customContent = toolTipContent(); + if (customContent.image().isNull()) { + tipData.setImage(KIcon("chronometer").pixmap(IconSize(KIconLoader::Desktop))); + } else { + tipData.setImage(customContent.image()); + } + + if (!customContent.mainText().isEmpty()) { + // add their main text + tipData.setMainText(customContent.mainText() + "
    " + tipData.mainText()); + } + + if (!customContent.subText().isEmpty()) { + // add their sub text + tipData.setSubText(customContent.subText() + "
    " + tipData.subText()); + } + + tipData.setAutohide(false); + Plasma::ToolTipManager::self()->setContent(this, tipData); +} + +Plasma::ToolTipContent ClockApplet::toolTipContent() +{ + return Plasma::ToolTipContent(); +} + +void ClockApplet::createConfigurationInterface(KConfigDialog *parent) +{ + createClockConfigurationInterface(parent); + + QWidget *widget = new QWidget(); + d->ui.setupUi(widget); + + parent->addPage(widget, i18n("Time Zones"), Applet::icon()); + + foreach (const QString &tz, d->selectedTimezones) { + d->ui.timeZones->setSelected(tz, true); + } + + updateClockDefaultsTo(); + int defaultSelection = d->ui.clockDefaultsTo->findText(currentTimezone()); + if (defaultSelection >= 0) { + d->ui.clockDefaultsTo->setCurrentIndex(defaultSelection); + } + + parent->setButtons( KDialog::Ok | KDialog::Cancel | KDialog::Apply ); + connect(parent, SIGNAL(applyClicked()), this, SLOT(configAccepted())); + connect(parent, SIGNAL(okClicked()), this, SLOT(configAccepted())); + connect(d->ui.timeZones, SIGNAL(itemSelectionChanged()), this, SLOT(updateClockDefaultsTo())); + +#if 0 +#ifdef CLOCK_APPLET_CONF + ui.localTimeZone->setChecked(isLocalTimezone()); + ui.timeZones->setEnabled(!isLocalTimezone()); + foreach (const QString &str, selectedTimezones) { + ui.timeZones->setSelected(str, true); + } +#endif +#endif +} + +void ClockApplet::createClockConfigurationInterface(KConfigDialog *parent) +{ + Q_UNUSED(parent) +} + +void ClockApplet::clockConfigAccepted() +{ + +} + +void ClockApplet::configAccepted() +{ + KConfigGroup cg = config(); + + d->selectedTimezones = d->ui.timeZones->selection(); + cg.writeEntry("timeZones", d->selectedTimezones); + + QString newTimezone; + + if (d->ui.clockDefaultsTo->currentIndex() == 0) { + //The first position in ui.clockDefaultsTo is "Local" + newTimezone = localTimezone(); + } else { + newTimezone = d->ui.clockDefaultsTo->currentText(); + } + + changeEngineTimezone(currentTimezone(), newTimezone); + setCurrentTimezone(newTimezone); + + clockConfigAccepted(); + constraintsEvent(Plasma::SizeConstraint); + update(); + + emit configNeedsSaving(); +} + +void ClockApplet::updateClockDefaultsTo() +{ + QString oldSelection = d->ui.clockDefaultsTo->currentText(); + d->ui.clockDefaultsTo->clear(); + d->ui.clockDefaultsTo->addItems(d->ui.timeZones->selection()); + d->ui.clockDefaultsTo->insertItem(0, "Local"); + int newPosition = d->ui.clockDefaultsTo->findText(oldSelection); + if (newPosition >= 0) { + d->ui.clockDefaultsTo->setCurrentIndex(newPosition); + } + if (d->ui.clockDefaultsTo->count() > 1) { + d->ui.clockDefaultsTo->setEnabled(true); + } + else { + // Only "Local" in ui.clockDefaultsTo + d->ui.clockDefaultsTo->setEnabled(false); + } +} + +void ClockApplet::changeEngineTimezone(const QString &oldTimezone, const QString &newTimezone) +{ + // reimplemented by subclasses to get the new data + Q_UNUSED(oldTimezone); + Q_UNUSED(newTimezone); +} + +void ClockApplet::wheelEvent(QGraphicsSceneWheelEvent *event) +{ + if (d->selectedTimezones.count() < 1) { + return; + } + + QString newTimezone; + + if (isLocalTimezone()) { + if (event->delta() > 0) { + newTimezone = d->selectedTimezones.last(); + } else { + newTimezone = d->selectedTimezones.first(); + } + } else { + int current = d->selectedTimezones.indexOf(currentTimezone()); + + if (event->delta() > 0) { + int previous = current - 1; + if (previous < 0) { + newTimezone = localTimezone(); + } else { + newTimezone = d->selectedTimezones.at(previous); + } + } else { + int next = current + 1; + if (next > d->selectedTimezones.count() - 1) { + newTimezone = localTimezone(); + } else { + newTimezone = d->selectedTimezones.at(next); + } + } + } + + changeEngineTimezone(currentTimezone(), newTimezone); + setCurrentTimezone(newTimezone); + + update(); +} + +void ClockApplet::initExtenderItem(Plasma::ExtenderItem *item) +{ + Plasma::Calendar *calendar = new Plasma::Calendar; + calendar->setMinimumSize(QSize(200, 180)); + + Plasma::DataEngine::Data data = dataEngine("time")->query(currentTimezone()); + QDate date = data["Date"].toDate(); + if (date.isValid()) { + calendar->setDate(date); + } + + item->setWidget(calendar); + item->setTitle(i18n("Calendar")); +} + +void ClockApplet::init() +{ + KConfigGroup cg = config(); + d->selectedTimezones = cg.readEntry("timeZones", QStringList()); + d->timezone = cg.readEntry("timezone", d->timezone); + if (d->timezone == "UTC") { + d->prettyTimezone = d->timezone; + } else { + if (!isLocalTimezone()) { + QStringList tzParts = d->timezone.split("/"); + d->prettyTimezone = tzParts.value(1); + } else { + d->prettyTimezone = localTimezone(); + } + } + + //avoid duplication + if (!extender()->item("calendar")) { + Plasma::ExtenderItem *eItem = new Plasma::ExtenderItem(extender()); + eItem->setName("calendar"); + initExtenderItem(eItem); + } + + Plasma::ToolTipManager::self()->registerWidget(this); +} + +void ClockApplet::setCurrentTimezone(const QString &tz) +{ + if (d->timezone == tz) { + return; + } + + d->timezone = tz; + if (tz == "UTC") { + d->prettyTimezone = tz; + } else { + QStringList tzParts = tz.split("/"); + d->prettyTimezone = tzParts.value(1); + } + KConfigGroup cg = config(); + cg.writeEntry("timezone", tz); + emit configNeedsSaving(); +} + +QString ClockApplet::currentTimezone() const +{ + return d->timezone; +} + +QString ClockApplet::prettyTimezone() const +{ + return d->prettyTimezone; +} + +QStringList ClockApplet::getSelectedTimezones() const +{ + return d->selectedTimezones; +} + +bool ClockApplet::isLocalTimezone() const +{ + return d->timezone == localTimezone(); +} + +QString ClockApplet::localTimezone() +{ + return "Local"; +} + +#include "clockapplet.moc" diff --git a/libplasmaclock/clockapplet.h b/libplasmaclock/clockapplet.h new file mode 100644 index 000000000..e8ad96708 --- /dev/null +++ b/libplasmaclock/clockapplet.h @@ -0,0 +1,82 @@ +/*************************************************************************** + * Copyright (C) 2007-2008 by Riccardo Iaconelli * + * Copyright (C) 2007-2008 by Sebastian Kuegler * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * + ***************************************************************************/ + +#ifndef CLOCKAPPLET_H +#define CLOCKAPPLET_H + +#include +#include + +#include +#include +#include +#include + +#include "plasmaclock_export.h" + +class KDialog; +class KConfigDialog; + +namespace Plasma +{ + class Svg; +} + +class PLASMACLOCK_EXPORT ClockApplet : public Plasma::PopupApplet +{ + Q_OBJECT + public: + ClockApplet(QObject *parent, const QVariantList &args); + ~ClockApplet(); + + void init(); + + QString currentTimezone() const; + QString prettyTimezone() const; + bool isLocalTimezone() const; + QStringList getSelectedTimezones() const; + + static QString localTimezone(); + + public Q_SLOTS: + void toolTipAboutToShow(); + void toolTipHidden(); + + protected: + virtual void createClockConfigurationInterface(KConfigDialog *parent); + virtual void clockConfigAccepted(); + virtual void changeEngineTimezone(const QString &oldTimezone, const QString &newTimezone); + virtual Plasma::ToolTipContent toolTipContent(); + void wheelEvent(QGraphicsSceneWheelEvent *event); + void createConfigurationInterface(KConfigDialog *parent); + void initExtenderItem(Plasma::ExtenderItem *item); + void updateContent(); + + protected Q_SLOTS: + void setCurrentTimezone(const QString &tz); + void configAccepted(); + void updateClockDefaultsTo(); + + private: + class Private; + Private * const d; +}; + +#endif diff --git a/libplasmaclock/clocknumber.cpp b/libplasmaclock/clocknumber.cpp new file mode 100644 index 000000000..da55853af --- /dev/null +++ b/libplasmaclock/clocknumber.cpp @@ -0,0 +1,71 @@ +/*************************************************************************** +* Copyright (C) 2007 by Riccardo Iaconelli * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License for more details. * +* * +* You should have received a copy of the GNU General Public License * +* along with this program; if not, write to the * +* Free Software Foundation, Inc., * +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * +***************************************************************************/ + +#include "clocknumber.h" + +class Number::Private +{ + public: + char data; +}; + +Number::Number(QChar value) + : d(new Private) +{ + d->data = value.toAscii(); +} + +Number::~Number() +{ + delete d; +} + +void Number::operator--() +{ + if (d->data == '0') { + d->data = '9'; + } else { + d->data--; + } +} + +void Number::operator++() +{ + if (d->data == '9') { + d->data = '0'; + } else { + d->data++; + } +} + +void Number::operator=(QChar value) +{ + d->data = value.toAscii(); +} + +bool Number::operator==(char value) +{ + return d->data == value; +} + +Number::operator char() +{ + return d->data; +} + diff --git a/libplasmaclock/clocknumber.h b/libplasmaclock/clocknumber.h new file mode 100644 index 000000000..916d6c16f --- /dev/null +++ b/libplasmaclock/clocknumber.h @@ -0,0 +1,43 @@ +/*************************************************************************** +* Copyright (C) 2007 by Riccardo Iaconelli * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License for more details. * +* * +* You should have received a copy of the GNU General Public License * +* along with this program; if not, write to the * +* Free Software Foundation, Inc., * +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * +***************************************************************************/ + +#ifndef CLOCKNUMBER_H +#define CLOCKNUMBER_H + +#include +#include "plasmaclock_export.h" + +class PLASMACLOCK_EXPORT Number +{ + public: + Number(QChar value); + ~Number(); + void operator--(); + void operator++(); + void operator=(QChar value); + bool operator==(char value); + operator char(); + + private: + class Private; + Private * const d; +}; + +#endif + diff --git a/libplasmaclock/plasmaclock_export.h b/libplasmaclock/plasmaclock_export.h new file mode 100644 index 000000000..95ad6009f --- /dev/null +++ b/libplasmaclock/plasmaclock_export.h @@ -0,0 +1,40 @@ +/* This file is part of the KDE project + Copyright (C) 2007 David Faure + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This 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 PLASMACLOCK_EXPORT_H +#define PLASMACLOCK_EXPORT_H + +/* needed for KDE_EXPORT and KDE_IMPORT macros */ +#include + +#ifndef PLASMACLOCK_EXPORT +# if defined(MAKE_PLASMACLOCK_LIB) + /* We are building this library */ +# define PLASMACLOCK_EXPORT KDE_EXPORT +# else + /* We are using this library */ +# define PLASMACLOCK_EXPORT KDE_IMPORT +# endif +#endif + +# ifndef PLASMACLOCK_EXPORT_DEPRECATED +# define PLASMACLOCK_EXPORT_DEPRECATED KDE_DEPRECATED PLASMACLOCK_EXPORT +# endif + +#endif diff --git a/libplasmaclock/timezonesConfig.ui b/libplasmaclock/timezonesConfig.ui new file mode 100644 index 000000000..5e9eedbe1 --- /dev/null +++ b/libplasmaclock/timezonesConfig.ui @@ -0,0 +1,96 @@ + + timezonesConfig + + + + 0 + 0 + 308 + 227 + + + + + + + + 300 + 150 + + + + Select one or several time zones. + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Your <span style=" font-weight:600;">Local</span> time and time zone are defined in System Settings, in the Date and Time tab. As default, your plasma clock will use this setting.</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The plasma clock tooltip can display the time in several other time zones: to do so, select one or several more time zones in the list. Click on a line to select it and click on it again to deselect it. </p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">After you validate your choices with the OK button, when your mouse is over the clock, a tooltip will display the time in all the selected time zones.</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">To select a <span style=" font-weight:600;">Default</span> time zone: you can either scroll over the clock with your mouse wheel and set the one you want or you can set it with "Clock defaults to:". .</p></body></html> + + + QAbstractItemView::MultiSelection + + + + Area + + + + + Region + + + + + Comment + + + + + + + + + + Clock defaults to: + + + + + + + + 0 + 0 + + + + The time the clock will display + + + The clock will display the time for the selected default zone. +Local is the time you set in System Settings. + + + QComboBox::InsertAlphabetically + + + + + + + + + + KTimeZoneWidget + QTreeWidget +
    ktimezonewidget.h
    +
    +
    + + +
    diff --git a/libplasmaclock/toolbutton.cpp b/libplasmaclock/toolbutton.cpp new file mode 100644 index 000000000..3d8a7e552 --- /dev/null +++ b/libplasmaclock/toolbutton.cpp @@ -0,0 +1,127 @@ +/* + * Copyright 2008 Marco Martin + * Copyright 2008 Aaron Seigo + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "toolbutton.h" + +#include +#include +#include +#include +#include + +#include +#include +#include + +ToolButton::ToolButton() + : QToolButton(), + m_action(0) +{ + setAttribute(Qt::WA_NoSystemBackground); + + m_background = new Plasma::FrameSvg(this); + m_background->setImagePath("widgets/button"); + m_background->setCacheAllRenderedFrames(true); + m_background->setElementPrefix("plain"); +} + + +ToolButton::ToolButton(QWidget *parent) + : QToolButton(parent), + m_action(0) +{ + m_background = new Plasma::FrameSvg(this); + m_background->setImagePath("widgets/button"); + m_background->setCacheAllRenderedFrames(true); + m_background->setElementPrefix("plain"); +} + +void ToolButton::setAction(QAction *action) +{ + if (!action) { + return; + } + + if (m_action) { + disconnect(m_action, SIGNAL(changed()), this, SLOT(syncToAction())); + disconnect(this, SIGNAL(clicked()), m_action, SLOT(trigger())); + } + + m_action = action; + connect(m_action, SIGNAL(changed()), this, SLOT(syncToAction())); + connect(this, SIGNAL(clicked()), m_action, SLOT(trigger())); + connect(m_action, SIGNAL(destroyed(QObject*)), this, SLOT(actionDestroyed(QObject*))); + syncToAction(); +} + +void ToolButton::syncToAction() +{ + if (!m_action) { + return; + } + + setIcon(m_action->icon()); + setText(m_action->text()); + + if (toolButtonStyle() == Qt::ToolButtonIconOnly) { + setToolTip(m_action->text()); + } + + setCheckable(m_action->isCheckable()); + if (m_action->actionGroup()) { + setAutoExclusive(m_action->actionGroup()->isExclusive()); + } + + setEnabled(m_action->isEnabled()); +} + +void ToolButton::actionDestroyed(QObject *) +{ + m_action = 0; +} + +void ToolButton::paintEvent(QPaintEvent *event) +{ + Q_UNUSED(event) + + QPainter painter(this); + + QStyleOptionToolButton buttonOpt; + initStyleOption(&buttonOpt); + + if ((buttonOpt.state & QStyle::State_MouseOver) || (buttonOpt.state & QStyle::State_On)) { + if (buttonOpt.state & QStyle::State_Sunken || (buttonOpt.state & QStyle::State_On)) { + m_background->setElementPrefix("pressed"); + } else { + m_background->setElementPrefix("normal"); + } + m_background->resizeFrame(size()); + m_background->paintFrame(&painter); + + buttonOpt.palette.setColor(QPalette::ButtonText, Plasma::Theme::defaultTheme()->color(Plasma::Theme::ButtonTextColor)); + } else { + buttonOpt.palette.setColor(QPalette::ButtonText, Plasma::Theme::defaultTheme()->color(Plasma::Theme::TextColor)); + } + + style()->drawControl(QStyle::CE_ToolButtonLabel, &buttonOpt, &painter, this); +} + +#include "toolbutton.moc" + diff --git a/libplasmaclock/toolbutton.h b/libplasmaclock/toolbutton.h new file mode 100644 index 000000000..51337f6ac --- /dev/null +++ b/libplasmaclock/toolbutton.h @@ -0,0 +1,53 @@ +/* + * Copyright 2008 Marco Martin + * Copyright 2008 Aaron Seigo + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef TOOLBUTTON_H +#define TOOLBUTTON_H + +#include + +namespace Plasma +{ + class FrameSvg; +} + +class ToolButton: public QToolButton +{ + Q_OBJECT + +public: + ToolButton(); + ToolButton(QWidget *parent); + void setAction(QAction *action); + +protected: + void paintEvent(QPaintEvent *event); + +protected slots: + void actionDestroyed(QObject *); + void syncToAction(); + +private: + QAction *m_action; + Plasma::FrameSvg *m_background; +}; + +#endif + diff --git a/nepomukquery/CMakeLists.txt b/nepomukquery/CMakeLists.txt new file mode 100644 index 000000000..dd8d65e40 --- /dev/null +++ b/nepomukquery/CMakeLists.txt @@ -0,0 +1,41 @@ +project(nepomukquery) + +include_directories( + ${QT_INCLUDES} + ${KDE4_INCLUDES} + ${CMAKE_SOURCE_DIR} + ${SOPRANO_INCLUDE_DIR} + ${NEPOMUK_INCLUDE_DIR} + ) + +add_definitions (${QT_DEFINITIONS} ${KDE4_DEFINITIONS})# -fPIC) + +set(nepomukquery_SRC + result.cpp + term.cpp + query.cpp + queryparser.cpp + dbusoperators.cpp +) + +kde4_add_library(nepomukquery SHARED ${nepomukquery_SRC} +) + +set_target_properties(nepomukquery PROPERTIES VERSION ${GENERIC_LIB_VERSION} SOVERSION ${GENERIC_LIB_SOVERSION}) + +target_link_libraries(nepomukquery + ${QT_QTCORE_LIBRARY} + ${KDE4_KDECORE_LIBS} + ${SOPRANO_LIBRARIES} + ) + +install(TARGETS nepomukquery ${INSTALL_TARGETS_DEFAULT_ARGS}) + +install(FILES + nepomukquery_export.h + queryparser.h + result.h + term.h + query.h + DESTINATION ${INCLUDE_INSTALL_DIR}/nepomuk +) diff --git a/nepomukquery/Messages.sh b/nepomukquery/Messages.sh new file mode 100755 index 000000000..b35f8c9a4 --- /dev/null +++ b/nepomukquery/Messages.sh @@ -0,0 +1,2 @@ +#! /usr/bin/env bash +$XGETTEXT *.cpp -o $podir/nepomuksearch.pot diff --git a/nepomukquery/dbusoperators.cpp b/nepomukquery/dbusoperators.cpp new file mode 100644 index 000000000..edc32beb6 --- /dev/null +++ b/nepomukquery/dbusoperators.cpp @@ -0,0 +1,341 @@ +/* + Copyright (c) 2008 Sebastian Trueg + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "dbusoperators.h" + +#include + + +Q_DECLARE_METATYPE(Nepomuk::Search::Result) +Q_DECLARE_METATYPE(Nepomuk::Search::Term) +Q_DECLARE_METATYPE(Nepomuk::Search::Query) +Q_DECLARE_METATYPE(Soprano::Node) +Q_DECLARE_METATYPE(QList) +Q_DECLARE_METATYPE(QList) + + +void Nepomuk::Search::registerDBusTypes() +{ + qDBusRegisterMetaType(); + qDBusRegisterMetaType >(); + qDBusRegisterMetaType(); + qDBusRegisterMetaType(); + qDBusRegisterMetaType(); +} + + +QDBusArgument& operator<<( QDBusArgument& arg, const Nepomuk::Search::Result& result ) +{ + // + // Signature: (sda{s(isss)}) + // + + arg.beginStructure(); + + arg << result.resourceUri().toString() << result.score(); + + arg.beginMap( QVariant::String, qMetaTypeId() ); + + QHash rp = result.requestProperties(); + for ( QHash::const_iterator it = rp.constBegin(); it != rp.constEnd(); ++it ) { + arg.beginMapEntry(); + arg << it.key().toString() << it.value(); + arg.endMapEntry(); + } + + arg.endMap(); + + arg.endStructure(); + + return arg; +} + + +const QDBusArgument& operator>>( const QDBusArgument& arg, Nepomuk::Search::Result& result ) +{ + // + // Signature: (sda{s(isss)}) + // + + arg.beginStructure(); + QString uri; + double score = 0.0; + + arg >> uri >> score; + result = Nepomuk::Search::Result( QUrl( uri ), score ); + + arg.beginMap(); + while ( !arg.atEnd() ) { + QString rs; + Soprano::Node node; + arg.beginMapEntry(); + arg >> rs >> node; + arg.endMapEntry(); + result.addRequestProperty( QUrl( rs ), node ); + } + arg.endMap(); + + arg.endStructure(); + + return arg; +} + + +QDBusArgument& operator<<( QDBusArgument& arg, const Nepomuk::Search::Term& term ) +{ + // + // Signature: (ii(isss)sss) + // i -> type + // i -> comparator type + // (isss) -> Soprano::LiteralValue encoded as a Soprano::Node for simplicity + // s -> resource + // s -> field + // s -> property + // + + arg.beginStructure(); + arg << ( int )term.type() + << ( int )term.comparator() + << Soprano::Node( term.value() ) + << term.resource().toString() + << term.field() + << term.property().toString(); + arg.endStructure(); + + return arg; +} + + +const QDBusArgument& operator>>( const QDBusArgument& arg, Nepomuk::Search::Term& term ) +{ + // + // Signature: (ii(isss)sss) + // i -> type + // i -> comparator type + // (isss) -> Soprano::LiteralValue encoded as a Soprano::Node for simplicity + // s -> resource + // s -> field + // s -> property + // + + arg.beginStructure(); + int type = Nepomuk::Search::Term::InvalidTerm; + int comparator = Nepomuk::Search::Term::Equal; + Soprano::Node valueNode; + QString resource, field, property; + arg >> type + >> comparator + >> valueNode + >> resource + >> field + >> property; + term.setType( Nepomuk::Search::Term::Type( type ) ); + term.setComparator( Nepomuk::Search::Term::Comparator( comparator ) ); + if ( valueNode.isLiteral() ) + term.setValue( valueNode.literal() ); + if ( !resource.isEmpty() ) + term.setResource( QUrl( resource ) ); + if ( !field.isEmpty() ) + term.setField( field ); + if ( !property.isEmpty() ) + term.setProperty( QUrl( property ) ); + arg.endStructure(); + + return arg; +} + + +// streaming a Query object is a bit tricky as it is a set of nested Term objects +// DBus does not allow arbitrary nesting of objects, thus we use a little trick: +// We store all used Term objects in a list and use integer indices pointing into +// this list to describe the nesting within the Term objects. This also means that +// a Term's subTerm list is replaced with a list of indices +namespace { + /** + * Build term relations for the last term in the list + */ + void buildTermRelations( QList& terms, QHash >& termRelations ) { + QList subTerms = terms.last().subTerms(); + int termIndex = terms.count()-1; + for ( int i = 0; i < subTerms.count(); ++i ) { + terms.append( subTerms[i] ); + termRelations[termIndex].append( terms.count()-1 ); + buildTermRelations( terms, termRelations ); + } + } +} + +QDBusArgument& operator<<( QDBusArgument& arg, const Nepomuk::Search::Query& query ) +{ + // + // Signature: (isa(ii(isss)sss)a{iai}ia{sb}) + // i -> type + // s -> sparql query + // a(ii(isss)sss) -> array of terms (first is root term) + // a{iai} -> hash of term relations + // i -> limit + // a{sb} -> request properties + // + + arg.beginStructure(); + + arg << ( int )query.type() << query.sparqlQuery(); + + QList terms; + QHash > termRelations; + if ( query.type() == Nepomuk::Search::Query::PlainQuery ) { + terms.append( query.term() ); + buildTermRelations( terms, termRelations ); + } + arg << terms; + + arg.beginMap( QVariant::Int, qMetaTypeId >() ); + for( QHash >::const_iterator it = termRelations.constBegin(); + it != termRelations.constEnd(); ++it ) { + arg.beginMapEntry(); + arg << it.key() << it.value(); + arg.endMapEntry(); + } + arg.endMap(); + arg << query.limit(); + + arg.beginMap( QVariant::String, QVariant::Bool ); + QList requestProperties = query.requestProperties(); + foreach( const Nepomuk::Search::Query::RequestProperty& rp, requestProperties ) { + arg.beginMapEntry(); + arg << rp.first.toString() << rp.second; + arg.endMapEntry(); + } + arg.endMap(); + + arg.endStructure(); + + return arg; +} + + +namespace { + Nepomuk::Search::Term rebuildTermFromTermList( const QList& terms, + const QHash >& termRelations, + int index = 0 ) { + Nepomuk::Search::Term root = terms[index]; + foreach( int i, termRelations[index] ) { + root.addSubTerm( rebuildTermFromTermList( terms, termRelations, i ) ); + } + return root; + } +} + +const QDBusArgument& operator>>( const QDBusArgument& arg, Nepomuk::Search::Query& query ) +{ + // + // Signature: (isa(ii(isss)sss)a{iai}ia{sb}) + // i -> type + // s -> sparql query + // a(ii(isss)sss) -> array of terms (first is root term) + // a{iai} -> hash of term relations + // i -> limit + // a{sb} -> request properties + // + + arg.beginStructure(); + + int type = Nepomuk::Search::Query::InvalidQuery; + QString sparqlQuery; + QList terms; + QHash > termRelations; + int limit = 0; + + arg >> type + >> sparqlQuery + >> terms; + + arg.beginMap(); + while ( !arg.atEnd() ) { + int termIndex = 0; + QList indices; + arg.beginMapEntry(); + arg >> termIndex >> indices; + arg.endMapEntry(); + termRelations.insert( termIndex, indices ); + } + arg.endMap(); + + arg >> limit; + + arg.beginMap(); + while ( !arg.atEnd() ) { + QString prop; + bool optional = true; + arg.beginMapEntry(); + arg >> prop >> optional; + arg.endMapEntry(); + query.addRequestProperty( QUrl( prop ), optional ); + } + arg.endMap(); + + arg.endStructure(); + + if ( Nepomuk::Search::Query::Type( type ) == Nepomuk::Search::Query::PlainQuery ) { + query.setTerm( rebuildTermFromTermList( terms, termRelations ) ); + } + else { + query.setSparqlQuery( sparqlQuery ); + } + query.setLimit( limit ); + + return arg; +} + + +QDBusArgument& operator<<( QDBusArgument& arg, const Soprano::Node& node ) +{ + // + // Signature: (isss) + // + arg.beginStructure(); + arg << ( int )node.type() << node.toString() << node.language() << node.dataType().toString(); + arg.endStructure(); + return arg; +} + + +const QDBusArgument& operator>>( const QDBusArgument& arg, Soprano::Node& node ) +{ + // + // Signature: (isss) + // + arg.beginStructure(); + int type; + QString value, language, dataTypeUri; + arg >> type >> value >> language >> dataTypeUri; + if ( type == Soprano::Node::LiteralNode ) { + node = Soprano::Node( Soprano::LiteralValue::fromString( value, dataTypeUri ), language ); + } + else if ( type == Soprano::Node::ResourceNode ) { + node = Soprano::Node( QUrl( value ) ); + } + else if ( type == Soprano::Node::BlankNode ) { + node = Soprano::Node( value ); + } + else { + node = Soprano::Node(); + } + arg.endStructure(); + return arg; +} diff --git a/nepomukquery/dbusoperators.h b/nepomukquery/dbusoperators.h new file mode 100644 index 000000000..5e0a4c489 --- /dev/null +++ b/nepomukquery/dbusoperators.h @@ -0,0 +1,48 @@ +/* + Copyright (c) 2008 Sebastian Trueg + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef _NEPOMUK_SEARCH_DBUS_OPERATORS_H_ +#define _NEPOMUK_SEARCH_DBUS_OPERATORS_H_ + +#include + +#include "result.h" +#include "query.h" +#include "term.h" + +#include "nepomukquery_export.h" + +namespace Nepomuk { + namespace Search { + NEPOMUKQUERY_EXPORT void registerDBusTypes(); + } +} + +NEPOMUKQUERY_EXPORT QDBusArgument& operator<<( QDBusArgument& arg, const Soprano::Node& ); +NEPOMUKQUERY_EXPORT const QDBusArgument& operator>>( const QDBusArgument& arg, Soprano::Node& ); + +NEPOMUKQUERY_EXPORT QDBusArgument& operator<<( QDBusArgument& arg, const Nepomuk::Search::Term& term ); +NEPOMUKQUERY_EXPORT const QDBusArgument& operator>>( const QDBusArgument& arg, Nepomuk::Search::Term& ); + +NEPOMUKQUERY_EXPORT QDBusArgument& operator<<( QDBusArgument& arg, const Nepomuk::Search::Query& query ); +NEPOMUKQUERY_EXPORT const QDBusArgument& operator>>( const QDBusArgument& arg, Nepomuk::Search::Query& ); + +NEPOMUKQUERY_EXPORT QDBusArgument& operator<<( QDBusArgument& arg, const Nepomuk::Search::Result& ); +NEPOMUKQUERY_EXPORT const QDBusArgument& operator>>( const QDBusArgument& arg, Nepomuk::Search::Result& ); + +#endif diff --git a/nepomukquery/nepomukquery_export.h b/nepomukquery/nepomukquery_export.h new file mode 100644 index 000000000..a71cc1375 --- /dev/null +++ b/nepomukquery/nepomukquery_export.h @@ -0,0 +1,36 @@ +/* This file is part of the KDE project + Copyright (C) 2007 David Faure + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This 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 NEPOMUKQUERY_EXPORT_H +#define NEPOMUKQUERY_EXPORT_H + +/* needed for KDE_EXPORT and KDE_IMPORT macros */ +#include + +#ifndef NEPOMUKQUERY_EXPORT +# if defined(MAKE_NEPOMUKQUERY_LIB) + /* We are building this library */ +# define NEPOMUKQUERY_EXPORT KDE_EXPORT +# else + /* We are using this library */ +# define NEPOMUKQUERY_EXPORT KDE_IMPORT +# endif +#endif + +#endif diff --git a/nepomukquery/query.cpp b/nepomukquery/query.cpp new file mode 100644 index 000000000..a991865c2 --- /dev/null +++ b/nepomukquery/query.cpp @@ -0,0 +1,195 @@ +/* + This file is part of the Nepomuk KDE project. + Copyright (C) 2008 Sebastian Trueg + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + */ + +#include "query.h" +#include "term.h" + +#include +#include + + +class Nepomuk::Search::Query::Private : public QSharedData +{ +public: + Private() + : type( InvalidQuery ), + limit( 0 ) { + } + + Type type; + Term term; + QString sparqlQuery; + int limit; + + QList requestProperties; +}; + + +Nepomuk::Search::Query::Query() + : d( new Private() ) +{ +} + + +Nepomuk::Search::Query::Query( const Query& other ) +{ + d = other.d; +} + + +Nepomuk::Search::Query::Query( const Term& term ) + : d ( new Private() ) +{ + d->type = PlainQuery; + d->term = term; +} + + +Nepomuk::Search::Query::Query( const QString& sparqlQuery ) + : d ( new Private() ) +{ + d->type = SPARQLQuery; + d->sparqlQuery = sparqlQuery; +} + + +Nepomuk::Search::Query::~Query() +{ +} + + +Nepomuk::Search::Query& Nepomuk::Search::Query::operator=( const Query& other ) +{ + d = other.d; + return *this; +} + + +Nepomuk::Search::Query::Type Nepomuk::Search::Query::type() const +{ + return d->type; +} + + +Nepomuk::Search::Term Nepomuk::Search::Query::term() const +{ + return d->term; +} + + +int Nepomuk::Search::Query::limit() const +{ + return d->limit; +} + + +QString Nepomuk::Search::Query::sparqlQuery() const +{ + return d->sparqlQuery; +} + + +void Nepomuk::Search::Query::setTerm( const Term& term ) +{ + d->term = term; + d->type = PlainQuery; +} + + +void Nepomuk::Search::Query::setLimit( int limit ) +{ + d->limit = limit; +} + + +void Nepomuk::Search::Query::setSparqlQuery( const QString& qs ) +{ + d->sparqlQuery = qs; + d->term = Term(); + d->type = SPARQLQuery; +} + + +void Nepomuk::Search::Query::addRequestProperty( const QUrl& property, bool optional ) +{ + d->requestProperties.append( qMakePair( property, optional ) ); +} + + +void Nepomuk::Search::Query::clearRequestProperties() +{ + d->requestProperties.clear(); +} + + +QList Nepomuk::Search::Query::requestProperties() const +{ + return d->requestProperties; +} + + +namespace { + bool compareRequestProperties( const QList& rp1, const QList& rp2 ) { + // brute force + foreach( const Nepomuk::Search::Query::RequestProperty& rp, rp1 ) { + if ( !rp2.contains( rp ) ) { + return false; + } + } + foreach( const Nepomuk::Search::Query::RequestProperty& rp, rp2 ) { + if ( !rp1.contains( rp ) ) { + return false; + } + } + return true; + } +} + +bool Nepomuk::Search::Query::operator==( const Query& other ) const +{ + if ( d->type == other.d->type && + d->limit == other.d->limit ) { + if ( d->type == SPARQLQuery ) { + return( d->sparqlQuery == other.d->sparqlQuery && + compareRequestProperties( d->requestProperties, other.d->requestProperties ) ); + } + else { + return( d->term == other.d->term && + compareRequestProperties( d->requestProperties, other.d->requestProperties ) ); + } + } + + return false; +} + + +QDebug operator<<( QDebug dbg, const Nepomuk::Search::Query& query ) +{ + dbg << "(Query" << query.term() << query.limit() << ")"; + return dbg; +} + + +uint Nepomuk::Search::qHash( const Nepomuk::Search::Query& query ) +{ + if ( query.type() == Nepomuk::Search::Query::SPARQLQuery ) + return qHash( query.sparqlQuery() ); + else + return qHash( query.term() ); +} diff --git a/nepomukquery/query.h b/nepomukquery/query.h new file mode 100644 index 000000000..015befce6 --- /dev/null +++ b/nepomukquery/query.h @@ -0,0 +1,122 @@ +/* + This file is part of the Nepomuk KDE project. + Copyright (C) 2008 Sebastian Trueg + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + */ + +#ifndef _NEPOMUK_SEARCH_QUERY_H_ +#define _NEPOMUK_SEARCH_QUERY_H_ + +#include +#include +#include +#include + +#include "nepomukquery_export.h" + +class QUrl; + +namespace Nepomuk { + namespace Search { + + class Term; + + /** + * \class Query query.h nepomuk/query.h + * + * \brief A Nepomuk desktop query. + * + * A query can either be based on Term or a more complex + * SPARQL query. + * + * \author Sebastian Trueg + */ + class NEPOMUKQUERY_EXPORT Query + { + public: + enum Type { + InvalidQuery, + PlainQuery, + SPARQLQuery + }; + + /** + * Create an empty invalid query object. + */ + Query(); + + /** + * Create a query of type PlainQuery based on + * \a term. + */ + Query( const Term& term ); + + /** + * Create a SPARQL query. The query has to have one select variable called "?r" + */ + explicit Query( const QString& sparqlQuery ); + + /** + * Copy constructor. + */ + Query( const Query& ); + + /** + * Destructor + */ + ~Query(); + + /** + * Assignment operator + */ + Query& operator=( const Query& ); + + Type type() const; + Term term() const; + QString sparqlQuery() const; + int limit() const; + + void setTerm( const Term& ); + void setSparqlQuery( const QString& ); + void setLimit( int ); + + /** + * Add a property that should be reported with each search result. + * \param property The requested property. + * \param optional If \p true the property is optional, meaning it can + * be empty ins earch results. + */ + void addRequestProperty( const QUrl& property, bool optional = true ); + void clearRequestProperties(); + + typedef QPair RequestProperty; + + QList requestProperties() const; + + bool operator==( const Query& ) const; + + private: + class Private; + QSharedDataPointer d; + }; + + NEPOMUKQUERY_EXPORT uint qHash( const Nepomuk::Search::Query& ); + } +} + +NEPOMUKQUERY_EXPORT QDebug operator<<( QDebug, const Nepomuk::Search::Query& ); + +#endif diff --git a/nepomukquery/queryparser.cpp b/nepomukquery/queryparser.cpp new file mode 100644 index 000000000..78cfbbf82 --- /dev/null +++ b/nepomukquery/queryparser.cpp @@ -0,0 +1,279 @@ +/* + This file is part of the Nepomuk KDE project. + Copyright (C) 2007 Sebastian Trueg + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + */ + +#include "queryparser.h" +#include "query.h" +#include "term.h" + +#include +#include + +#include +#include + + +/* Advanced queries: + * select distinct ?r ?p ?x ?label ?comment where { { ?r ?p ?x . } UNION { ?r ?p ?r2 . ?r2 ?p2 ?x . } . FILTER(isLiteral(?x)) . FILTER REGEX(STR(?p),'hastag','i') . FILTER REGEX(STR(?x),'nepomuk','i') . OPTIONAL { { ?r ?label } UNION { ?r ?label . } UNION { ?r ?label . } . ?r ?comment . } . } + */ + +namespace { + // a field differs from a plain term in that it does never allow comparators + QString s_fieldNamePattern( "([^\\s\"':=<>]+|(?:([\"'])[^\"':=<>]+\\%1))" ); + QString s_plainTermPattern( "([^\\s\"':=<>]+|(?:([\"'])[^\"']+\\%1))" ); + QString s_inExclusionPattern( "([\\+\\-]?)" ); + QString s_uriPattern( "<([^<>]+)>" ); + QString s_comparatorPattern( "(:|\\<=|\\>=|=|\\<|\\>)" ); + + // match a simple search text + // captures: 1 - The optional + or - sign (may be empty) + // 2 - the search text (including optional paranthesis) + QRegExp s_plainTermRx( s_inExclusionPattern + s_plainTermPattern.arg( 3 ) ); + + // match a field search term: fieldname + relation (:, =, etc) + search text with optional paranthesis + // captures: 1 - The optional + or - sign (may be empty) + // 2 - fieldname + // 3 - relation + // 4 - search text (including optional paranthesis) + QRegExp s_fieldRx( s_inExclusionPattern + s_fieldNamePattern.arg( 3 ) + s_comparatorPattern + s_plainTermPattern.arg( 6 ) ); + + // match a property URI search term: property URI + relation (:, =, etc) + search text with optional paranthesis + // captures: 1 - The optional + or - sign (may be empty) + // 2 - property URI + // 3 - relation + // 4 - search text (including optional paranthesis) + QRegExp s_propertyRx( s_inExclusionPattern + s_uriPattern + s_comparatorPattern + s_plainTermPattern.arg( 5 ) ); + + // match a property URI search term: property URI + relation (:, =, etc) + resource URI + // captures: 1 - The optional + or - sign (may be empty) + // 2 - property URI + // 3 - resource URI + QRegExp s_resourceRx( s_inExclusionPattern + s_uriPattern + "(?::|=)" + s_uriPattern ); + + QRegExp s_fieldFieldRx( s_inExclusionPattern + s_fieldNamePattern.arg( 3 ) + s_comparatorPattern + "\\(" + s_fieldNamePattern.arg( 6 ) + s_comparatorPattern + s_plainTermPattern.arg( 9 ) + "\\)" ); + + Nepomuk::Search::Term::Comparator fieldTypeRelationFromString( const QString& s ) { + if ( s == "=" ) { + return Nepomuk::Search::Term::Equal; + } + else if ( s == ":" ) { + return Nepomuk::Search::Term::Contains; + } + else if ( s == ">" ) { + return Nepomuk::Search::Term::Greater; + } + else if ( s == "<" ) { + return Nepomuk::Search::Term::Smaller; + } + else if ( s == ">=" ) { + return Nepomuk::Search::Term::GreaterOrEqual; + } + else if ( s == "<=" ) { + return Nepomuk::Search::Term::SmallerOrEqual; + } + else { + kDebug() << "FIXME: Unsupported relation:" << s; + return Nepomuk::Search::Term::Equal; + } + } + + QString stripQuotes( const QString& s ) { + if ( s[0] == '\'' || + s[0] == '\"' ) { + return s.mid( 1 ).left( s.length()-2 ); + } + else { + return s; + } + } + + QUrl tryToBeIntelligentAboutParsingUrl( const QString& s ) { + if ( s.contains( '%' ) && !s.contains( '/' ) ) { + return QUrl::fromEncoded( s.toAscii() ); + } + else { + return QUrl( s ); + } + } + + Soprano::LiteralValue createLiteral( const QString& s ) { + bool b = false; + int i = s.toInt( &b ); + if ( b ) + return Soprano::LiteralValue( i ); + double d = s.toDouble( &b ); + if ( b ) + return Soprano::LiteralValue( d ); + return s; + } +} + + +Nepomuk::Search::Query Nepomuk::Search::QueryParser::parseQuery( const QString& query ) +{ + QueryParser parser; + return parser.parse( query ); +} + + +class Nepomuk::Search::QueryParser::Private +{ +public: + QSet andKeywords; + QSet orKeywords; +}; + + +Nepomuk::Search::QueryParser::QueryParser() + : d( new Private() ) +{ + QString andListStr = i18nc( "Boolean AND keyword in desktop search strings. You can add several variants separated by spaces, e.g. retain the English one alongside the translation; keywords are not case sensitive. Make sure there is no conflict with the OR keyword.", "and" ); + foreach ( const QString &andKeyword, andListStr.split( " ", QString::SkipEmptyParts ) ) { + d->andKeywords.insert( andKeyword.toLower() ); + } + QString orListStr = i18nc( "Boolean OR keyword in desktop search strings. You can add several variants separated by spaces, e.g. retain the English one alongside the translation; keywords are not case sensitive. Make sure there is no conflict with the AND keyword.", "or" ); + foreach ( const QString &orKeyword, orListStr.split( " ", QString::SkipEmptyParts ) ) { + d->orKeywords.insert( orKeyword.toLower() ); + } +} + + +Nepomuk::Search::QueryParser::~QueryParser() +{ + delete d; +} + + +Nepomuk::Search::Query Nepomuk::Search::QueryParser::parse( const QString& query ) +{ + // TODO: a "real" parser which can handle all of the Xesam user language + // This one for example does not handle nesting at all. + + QList terms; + + bool inOrBlock = false; + bool inAndBlock = false; + + int pos = 0; + while ( pos < query.length() ) { + // skip whitespace + while ( pos < query.length() && query[pos].isSpace() ) { + kDebug() << "Skipping space at" << pos; + ++pos; + } + + Term term; + + if ( pos < query.length() ) { + if ( s_resourceRx.indexIn( query, pos ) == pos ) { + // FIXME: honour the +- + kDebug() << "matched resource term at" << pos << s_resourceRx.cap( 0 ); + term = Term( tryToBeIntelligentAboutParsingUrl( s_resourceRx.cap( 2 ) ), + tryToBeIntelligentAboutParsingUrl( s_resourceRx.cap( 3 ) ) ); + pos += s_resourceRx.matchedLength(); + } + else if ( s_propertyRx.indexIn( query, pos ) == pos ) { + // FIXME: honour the +- + kDebug() << "matched property term at" << pos << s_propertyRx.cap( 0 ); + term.setProperty( tryToBeIntelligentAboutParsingUrl( s_propertyRx.cap( 2 ) ) ); + term.addSubTerm( Term( createLiteral( stripQuotes( s_propertyRx.cap( 4 ) ) ) ) ); + QString comparator = s_propertyRx.cap( 3 ); + term.setType( Term::ComparisonTerm ); + term.setComparator( fieldTypeRelationFromString( comparator ) ); + pos += s_propertyRx.matchedLength(); + } + else if ( s_fieldFieldRx.indexIn( query, pos ) == pos ) { + kDebug() << "matched field field term at" << pos + << s_fieldFieldRx.cap( 0 ) + << s_fieldFieldRx.cap( 2 ) + << s_fieldFieldRx.cap( 4 ) + << s_fieldFieldRx.cap( 5 ) + << s_fieldFieldRx.cap( 7 ) + << s_fieldFieldRx.cap( 8 ); + term.setField( stripQuotes( s_fieldFieldRx.cap( 2 ) ) ); + QString comparator = s_fieldFieldRx.cap( 4 ); + term.setType( Term::ComparisonTerm ); + term.setComparator( fieldTypeRelationFromString( comparator ) ); + term.addSubTerm( Term( stripQuotes( s_fieldFieldRx.cap( 5 ) ), s_fieldFieldRx.cap( 8 ), fieldTypeRelationFromString( s_fieldFieldRx.cap( 7 ) ) ) ); + pos += s_fieldFieldRx.matchedLength(); + } + else if ( s_fieldRx.indexIn( query, pos ) == pos ) { + // FIXME: honour the +- + kDebug() << "matched field term at" << pos << s_fieldRx.cap( 0 ) << s_fieldRx.cap( 2 ) << s_fieldRx.cap( 4 ) << s_fieldRx.cap( 5 ); + term.setField( stripQuotes( s_fieldRx.cap( 2 ) ) ); + term.addSubTerm( Term( createLiteral( stripQuotes( s_fieldRx.cap( 5 ) ) ) ) ); + QString comparator = s_fieldRx.cap( 4 ); + term.setType( Term::ComparisonTerm ); + term.setComparator( fieldTypeRelationFromString( comparator ) ); + pos += s_fieldRx.matchedLength(); + } + else if ( s_plainTermRx.indexIn( query, pos ) == pos ) { + // FIXME: honour the +- + QString value = stripQuotes( s_plainTermRx.cap( 2 ) ); + if ( d->orKeywords.contains( value.toLower() ) ) { + inOrBlock = true; + } + else if ( d->andKeywords.contains( value.toLower() ) ) { + inAndBlock = true; + } + else { + kDebug() << "matched literal at" << pos << value; + term = Term( Soprano::LiteralValue( value ) ); + } + pos += s_plainTermRx.matchedLength(); + } + else { + kDebug() << "Invalid query at" << pos << query; + return Term(); + } + + if ( term.isValid() ) { + if ( inOrBlock && !terms.isEmpty() ) { + Term orTerm; + orTerm.setType( Term::OrTerm ); + orTerm.addSubTerm( terms.takeLast() ); + orTerm.addSubTerm( term ); + terms.append( orTerm ); + } + else if ( inAndBlock && !terms.isEmpty() ) { + Term andTerm; + andTerm.setType( Term::AndTerm ); + andTerm.addSubTerm( terms.takeLast() ); + andTerm.addSubTerm( term ); + terms.append( andTerm ); + } + else { + terms.append( term ); + } + } + } + } + + if ( terms.count() == 1 ) { + return terms[0]; + } + else if ( terms.count() > 0 ) { + Term t; + t.setType( Term::AndTerm ); + t.setSubTerms( terms ); + return t; + } + else { + return Term(); + } +} diff --git a/nepomukquery/queryparser.h b/nepomukquery/queryparser.h new file mode 100644 index 000000000..3f07253ff --- /dev/null +++ b/nepomukquery/queryparser.h @@ -0,0 +1,49 @@ +/* + This file is part of the Nepomuk KDE project. + Copyright (C) 2007 Sebastian Trueg + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + */ + +#ifndef _NEPOMUK_SEARCH_QUERY_PARSER_H_ +#define _NEPOMUK_SEARCH_QUERY_PARSER_H_ + +#include "query.h" + +#include + +#include "nepomukquery_export.h" + + +namespace Nepomuk { + namespace Search { + class NEPOMUKQUERY_EXPORT QueryParser + { + public: + QueryParser(); + ~QueryParser(); + + Query parse( const QString& query ); + + static Query parseQuery( const QString& query ); + + private: + class Private; + Private* const d; + }; + } +} + +#endif diff --git a/nepomukquery/qurlhash.h b/nepomukquery/qurlhash.h new file mode 100644 index 000000000..4dfc77496 --- /dev/null +++ b/nepomukquery/qurlhash.h @@ -0,0 +1,31 @@ +/* + This file is part of the Nepomuk KDE project. + Copyright (C) 2008 Sebastian Trueg + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef _QURL_HASH_H_ +#define _QURL_HASH_H_ + +#include + +inline uint qHash( const QUrl& url ) +{ + return qHash( url.toString() ); +} + + +#endif diff --git a/nepomukquery/result.cpp b/nepomukquery/result.cpp new file mode 100644 index 000000000..a3b5bf183 --- /dev/null +++ b/nepomukquery/result.cpp @@ -0,0 +1,139 @@ +/* + This file is part of the Nepomuk KDE project. + Copyright (C) 2008 Sebastian Trueg + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + */ + +#include "result.h" +#include "qurlhash.h" + +#include +#include + + +class Nepomuk::Search::Result::Private : public QSharedData +{ +public: + QUrl resource; + double score; + QHash requestProperties; +}; + + +Nepomuk::Search::Result::Result() + : d( new Private() ) +{ +} + + +Nepomuk::Search::Result::Result( const QUrl& uri, double score ) + : d( new Private() ) +{ + d->resource = uri; + d->score = score; +} + + +Nepomuk::Search::Result::Result( const Result& other ) +{ + d = other.d; +} + + +Nepomuk::Search::Result::~Result() +{ +} + + +Nepomuk::Search::Result& Nepomuk::Search::Result::operator=( const Result& other ) +{ + d = other.d; + return *this; +} + + +double Nepomuk::Search::Result::score() const +{ + return d->score; +} + + +QUrl Nepomuk::Search::Result::resourceUri() const +{ + return d->resource; +} + + +void Nepomuk::Search::Result::setScore( double score ) +{ + d->score = score; +} + + +void Nepomuk::Search::Result::addRequestProperty( const QUrl& property, const Soprano::Node& value ) +{ + d->requestProperties[property] = value; +} + + +Soprano::Node Nepomuk::Search::Result::operator[]( const QUrl& property ) const +{ + return requestProperty( property ); +} + + +Soprano::Node Nepomuk::Search::Result::requestProperty( const QUrl& property ) const +{ + QHash::const_iterator it = d->requestProperties.find( property ); + if ( it != d->requestProperties.end() ) { + return *it; + } + else { + return Soprano::Node(); + } +} + + +QHash Nepomuk::Search::Result::requestProperties() const +{ + return d->requestProperties; +} + + +bool Nepomuk::Search::Result::operator==( const Result& other ) const +{ + if ( d->resource != other.d->resource || + d->score != other.d->score ) { + return false; + } + for ( QHash::const_iterator it = d->requestProperties.constBegin(); + it != d->requestProperties.constEnd(); ++it ) { + QHash::const_iterator it2 = other.d->requestProperties.constFind( it.key() ); + if ( it2 == other.d->requestProperties.constEnd() || + it2.value() != it.value() ) { + return false; + } + } + for ( QHash::const_iterator it = other.d->requestProperties.constBegin(); + it != other.d->requestProperties.constEnd(); ++it ) { + QHash::const_iterator it2 = d->requestProperties.constFind( it.key() ); + if ( it2 == d->requestProperties.constEnd() || + it2.value() != it.value() ) { + return false; + } + } + return true; +} diff --git a/nepomukquery/result.h b/nepomukquery/result.h new file mode 100644 index 000000000..a018972cc --- /dev/null +++ b/nepomukquery/result.h @@ -0,0 +1,72 @@ +/* + This file is part of the Nepomuk KDE project. + Copyright (C) 2008 Sebastian Trueg + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + */ + +#ifndef _NEPOMUK_SEARCH_RESULT_H_ +#define _NEPOMUK_SEARCH_RESULT_H_ + +#include +#include +#include +#include + +#include + +#include "nepomukquery_export.h" + +namespace Nepomuk { + namespace Search { + /** + * \brief A single search result. + * + * A search returns a set of Result object. + * + * \author Sebastian Trueg + */ + class NEPOMUKQUERY_EXPORT Result + { + public: + Result(); + Result( const QUrl& uri, double score = 0.0 ); + Result( const Result& ); + ~Result(); + + Result& operator=( const Result& ); + + double score() const; + QUrl resourceUri() const; + + void setScore( double score ); + + void addRequestProperty( const QUrl& property, const Soprano::Node& value ); + + QHash requestProperties() const; + + Soprano::Node operator[]( const QUrl& property ) const; + Soprano::Node requestProperty( const QUrl& property ) const; + + bool operator==( const Result& ) const; + + private: + class Private; + QSharedDataPointer d; + }; + } +} + +#endif diff --git a/nepomukquery/term.cpp b/nepomukquery/term.cpp new file mode 100644 index 000000000..0a030f5bc --- /dev/null +++ b/nepomukquery/term.cpp @@ -0,0 +1,363 @@ +/* + This file is part of the Nepomuk KDE project. + Copyright (C) 2007 Sebastian Trueg + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + */ + +#include "term.h" + +#include +#include +#include +#include + + +class Nepomuk::Search::Term::Private : public QSharedData +{ +public: + Private( Type t = InvalidTerm, Comparator c = Equal ) + : type( t ), + comparator( c ) { + } + + Type type; + Comparator comparator; + Soprano::LiteralValue value; + QUrl resource; + QString field; + QUrl property; + QList subTerms; +}; + + +Nepomuk::Search::Term::Term() + : d( new Private() ) +{ +} + + +Nepomuk::Search::Term::Term( const Term& other ) +{ + d = other.d; +} + + +Nepomuk::Search::Term::Term( const Soprano::LiteralValue& value ) + : d( new Private( LiteralTerm ) ) +{ + d->value = value; +} + + +Nepomuk::Search::Term::Term( const QUrl& value ) + : d( new Private( ResourceTerm ) ) +{ + d->resource = value; +} + + +Nepomuk::Search::Term::Term( const QString& field, const Soprano::LiteralValue& value, Comparator c ) + : d( new Private( ComparisonTerm, c ) ) +{ + d->field = field; + d->subTerms.append( Term( value ) ); +} + + +Nepomuk::Search::Term::Term( const QUrl& field, const Soprano::LiteralValue& value, Comparator c ) + : d( new Private( ComparisonTerm, c ) ) +{ + d->property = field; + d->subTerms.append( Term( value ) ); +} + + +Nepomuk::Search::Term::Term( const QUrl& field, const QUrl& resource ) + : d( new Private( ComparisonTerm ) ) +{ + d->property = field; + d->subTerms.append( Term( resource ) ); +} + + +Nepomuk::Search::Term::~Term() +{ +} + + +Nepomuk::Search::Term& Nepomuk::Search::Term::operator=( const Term& other ) +{ + d = other.d; + return *this; +} + + +Nepomuk::Search::Term& Nepomuk::Search::Term::operator=( const Soprano::LiteralValue& literal ) +{ + d->value = literal; + d->type = LiteralTerm; + d->subTerms.clear(); + d->field = QString(); + return *this; +} + + +bool Nepomuk::Search::Term::isValid() const +{ + switch ( d->type ) { + case InvalidTerm: + return false; + + case LiteralTerm: + return d->value.isValid() && d->subTerms.isEmpty(); + + case ResourceTerm: + return d->resource.isValid() && d->subTerms.isEmpty(); + + case AndTerm: + case OrTerm: + return !d->subTerms.isEmpty(); + + case ComparisonTerm: + return ( !d->field.isEmpty() || !d->property.isEmpty() ) && ( d->subTerms.count() == 1 ); + } + // make gcc happy + return false; +} + + +Nepomuk::Search::Term::Type Nepomuk::Search::Term::type() const +{ + return d->type; +} + + +Soprano::LiteralValue Nepomuk::Search::Term::value() const +{ + return d->value; +} + + +QUrl Nepomuk::Search::Term::resource() const +{ + return d->resource; +} + + +Nepomuk::Search::Term::Comparator Nepomuk::Search::Term::comparator() const +{ + return d->comparator; +} + + +QString Nepomuk::Search::Term::field() const +{ + return d->field; +} + + +QUrl Nepomuk::Search::Term::property() const +{ + return d->property; +} + + +QList Nepomuk::Search::Term::subTerms() const +{ + return d->subTerms; +} + + +void Nepomuk::Search::Term::setType( Type type ) +{ + d->type = type; +} + + +void Nepomuk::Search::Term::setValue( const Soprano::LiteralValue& v ) +{ + d->value = v; + d->resource = QUrl(); +} + + +void Nepomuk::Search::Term::setResource( const QUrl& res ) +{ + d->resource = res; + d->value = Soprano::LiteralValue(); +} + + +void Nepomuk::Search::Term::setComparator( Comparator c ) +{ + d->comparator = c; +} + + +void Nepomuk::Search::Term::setField( const QString& f ) +{ + d->field = f; + d->property = QUrl(); +} + + +void Nepomuk::Search::Term::setSubTerms( const QList& terms ) +{ + d->subTerms = terms; +} + + +void Nepomuk::Search::Term::setProperty( const QUrl& p ) +{ + d->property = p; + d->field = QString(); +} + + +void Nepomuk::Search::Term::addSubTerm( const Term& term ) +{ + d->subTerms.append( term ); +} + + +namespace { + bool compareLists( const QList& t1, const QList& t2 ) { + // brute-force + foreach( const Nepomuk::Search::Term& t, t1 ) { + if ( !t2.contains( t ) ) { + return false; + } + } + foreach( const Nepomuk::Search::Term& t, t2 ) { + if ( !t1.contains( t ) ) { + return false; + } + } + return true; + } +} + +bool Nepomuk::Search::Term::operator==( const Term& other ) const +{ + if ( d->type == other.d->type ) { + if ( d->type == ComparisonTerm ) { + return ( d->comparator == other.d->comparator && + compareLists( d->subTerms, other.d->subTerms ) ); + } + else { + return d->value == other.d->value && + d->resource == other.d->resource && + d->field == other.d->field && + d->property == other.d->property && + compareLists( d->subTerms, other.d->subTerms ); + } + } + + return false; +} + + +QDebug operator<<( QDebug dbg, const Nepomuk::Search::Term& term ) +{ + if ( term.isValid() ) { + dbg << "(Term"; + switch( term.type() ) { + case Nepomuk::Search::Term::LiteralTerm: + dbg << "literal" << term.value(); + break; + case Nepomuk::Search::Term::ResourceTerm: + dbg << "resource" << term.resource(); + break; + case Nepomuk::Search::Term::AndTerm: + dbg << "and"; + break; + case Nepomuk::Search::Term::OrTerm: + dbg << "or"; + break; + case Nepomuk::Search::Term::ComparisonTerm: + dbg << "compare"; + switch( term.comparator() ) { + case Nepomuk::Search::Term::Contains: + dbg << ":"; + break; + case Nepomuk::Search::Term::Equal: + dbg << "="; + break; + case Nepomuk::Search::Term::Greater: + dbg << ">"; + break; + case Nepomuk::Search::Term::Smaller: + dbg << "<"; + break; + case Nepomuk::Search::Term::GreaterOrEqual: + dbg << ">="; + break; + case Nepomuk::Search::Term::SmallerOrEqual: + dbg << "<="; + break; + } + default: + break; + } + if ( term.type() == Nepomuk::Search::Term::ComparisonTerm ) { + if ( term.property().isValid() ) { + dbg << "Property" << term.property(); + } + else { + dbg << "Field:" << term.field(); + } + dbg << term.subTerms().first(); + } + if ( term.type() == Nepomuk::Search::Term::AndTerm || + term.type() == Nepomuk::Search::Term::OrTerm ) { + dbg << "Subterms: ["; + foreach( const Nepomuk::Search::Term &t, term.subTerms() ) { + dbg << t; + } + dbg << "]"; + } + dbg << ")"; + } + + return dbg; +} + + +uint Nepomuk::Search::qHash( const Nepomuk::Search::Term& term ) +{ + switch( term.type() ) { + case Nepomuk::Search::Term::LiteralTerm: + return qHash( term.value().toString() ); + + case Nepomuk::Search::Term::ComparisonTerm: + return( qHash( term.property().isValid() ? term.property().toString() : term.field() )<<16 | + qHash( term.subTerms().first() )<<8 | + ( uint )term.comparator() ); + + case Nepomuk::Search::Term::AndTerm: + case Nepomuk::Search::Term::OrTerm: { + uint h = ( uint )term.type(); + QList subTerms = term.subTerms(); + for ( int i = 0; i < subTerms.count(); ++i ) { + h |= ( qHash( subTerms[i] )< + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + */ + +#ifndef _NEPOMUK_SEARCH_TERM_H_ +#define _NEPOMUK_SEARCH_TERM_H_ + +#include +#include +#include + +#include + +#include "nepomukquery_export.h" + + +namespace Nepomuk { + namespace Search { + /** + * \class Term term.h nepomuk/term.h + * + * \brief A Query constist of Terms. + * + * Queries are build from Term instances. A Term can have one of multiple + * types and subterms. See Term::Type for details on the different Term types. + * + * \author Sebastian Trueg + */ + class NEPOMUKQUERY_EXPORT Term + { + public: + /** + * Each search term has a type. + */ + enum Type { + InvalidTerm, /**< An invalid term does not do anything */ + /** + * A literal term is the simplest form of Term. It matches all resource + * that contain the value. + * + * It is also used to specify literal values in comparison Terms such + * as ContainsTerm or EqualityTerm. + */ + LiteralTerm, + + /** + * A resource term matches one resource by URI. + * + * It is also used to specify a resource in EqualityTerm Terms. + */ + ResourceTerm, + + /** + * Match all resources that match all sub terms. + */ + AndTerm, + + /** + * Match all resources that match one of the sub terms. + */ + OrTerm, + + /** + * A comparison. The comparison operator needs to be specified in addition. + * For specifying the %property the same applies as for ContainsTerm. + * + * A single subterm specifies the resource or value to match (resource terms + * can only be matched via Equal or Contains. + */ + ComparisonTerm + }; + + enum Comparator { + Contains, + Equal, + Greater, + Smaller, + GreaterOrEqual, + SmallerOrEqual + }; + + /** + * Constructs an invalid term. + */ + Term(); + + /** + * Copy constructor. + */ + Term( const Term& other ); + + /** + * Construct a literal term. + */ + Term( const Soprano::LiteralValue& value ); + + /** + * Construct a resource term. + */ + Term( const QUrl& resource ); + + /** + * Construct a Contains ComparisonTerm term. + * \param field A string that will be matched against a field label + * \param value A value that will be matched against the field value. Unsupported + * types are converted to string. + * \param comparator The Comparator to use + */ + Term( const QString& field, const Soprano::LiteralValue& value, Comparator c = Contains ); + + /** + * Construct a Contains ComparisonTerm term. + * \param field The exact field to match + * \param value A value that will be matched against the field value. Unsupported + * types are converted to string. + * \param comparator The Comparator to use + */ + Term( const QUrl& field, const Soprano::LiteralValue& value, Comparator c = Contains ); + + /** + * Construct an EqualityTerm term. + * \param field The exact field to match + * \param value The resource that should be matched. + */ + Term( const QUrl& field, const QUrl& resource ); + + /** + * Destructor + */ + ~Term(); + + /** + * Assign another term to this one. + */ + Term& operator=( const Term& other ); + + /** + * Make the term a literal term. + */ + Term& operator=( const Soprano::LiteralValue& other ); + + /** + * \return \p true if the Term is valid. + */ + bool isValid() const; + + /** + * \return the Term type. + * + * \sa setType + */ + Type type() const; + + /** + * The literal value of a LiteralTerm. + * + * \sa setValue + */ + Soprano::LiteralValue value() const; + + /** + * The resource of a ResourceTerm + * + * \sa setResource + */ + QUrl resource() const; + + /** + * The Comparator used by ComparisonTerm Terms. + * + * \sa setComparator + */ + Comparator comparator() const; + + /** + * A property name used for ComparisonTerm Terms. Will be matched against + * the rdfs:label to find the corresponding property. + * + * \sa setField, property, setProperty + */ + QString field() const; + + /** + * A property used for ComparisonTerm Terms. + * + * \sa setProperty, field, setField + */ + QUrl property() const; + + /** + * The sub terms used by AndTerm, OrTerm, and ComparisonTerm. + * + * \sa setSubTerms, addSubTerm + */ + QList subTerms() const; + + /** + * Set the type of the Term + */ + void setType( Type ); + + /** + * Set the value of a LiteralTerm + */ + void setValue( const Soprano::LiteralValue& ); + + /** + * Set the resource of a ResourceTerm + */ + void setResource( const QUrl& ); + + /** + * Defaults to Equal + */ + void setComparator( Comparator ); + + /** + * Set the property label in case the exact + * property is not known. Will be mached against + * the property's rdfs:label. + * + * \sa field, setProperty, property + */ + void setField( const QString& ); + + /** + * Set the property for ComparisonTerm + * Terms. + * + * If the exact property is not known use setField. + * + * \sa property + */ + void setProperty( const QUrl& ); + + /** + * Set the subterms used by AndTerm, OrTerm, and ComparisonTerm. + * + * \sa addSubTerm + */ + void setSubTerms( const QList& ); + + /** + * Add a subterm used by AndTerm, OrTerm, and ComparisonTerm. + * + * \sa setSubTerm + */ + void addSubTerm( const Term& ); + + /** + * Comparison operator. + */ + bool operator==( const Term& ) const; + + private: + class Private; + QSharedDataPointer d; + }; + + NEPOMUKQUERY_EXPORT uint qHash( const Nepomuk::Search::Term& ); + } +} + +NEPOMUKQUERY_EXPORT QDebug operator<<( QDebug, const Nepomuk::Search::Term& ); + +#endif diff --git a/nepomukqueryclient/CMakeLists.txt b/nepomukqueryclient/CMakeLists.txt new file mode 100644 index 000000000..f41180c7a --- /dev/null +++ b/nepomukqueryclient/CMakeLists.txt @@ -0,0 +1,50 @@ +project(nepomukqueryclient) + +include_directories( + ${QT_INCLUDES} + ${KDE4_INCLUDES} + ${CMAKE_SOURCE_DIR} + ${SOPRANO_INCLUDE_DIR} + ${NEPOMUK_INCLUDE_DIR} + ${nepomukquery_SOURCE_DIR} + ) + +add_definitions (${QT_DEFINITIONS} ${KDE4_DEFINITIONS})# -fPIC) + +set(nepomukqueryclient_SRC + queryserviceclient.cpp +) + +set_source_files_properties( + org.kde.nepomuk.QueryService.xml + PROPERTIES INCLUDE "querymetatype.h") + +set_source_files_properties( + org.kde.nepomuk.Query.xml + PROPERTIES INCLUDE "result.h") + +qt4_add_dbus_interface(nepomukqueryclient_SRC + org.kde.nepomuk.QueryService.xml + queryserviceinterface) +qt4_add_dbus_interface(nepomukqueryclient_SRC + org.kde.nepomuk.Query.xml + queryinterface) + +kde4_add_library(nepomukqueryclient SHARED ${nepomukqueryclient_SRC}) + +set_target_properties(nepomukqueryclient PROPERTIES VERSION ${GENERIC_LIB_VERSION} SOVERSION ${GENERIC_LIB_SOVERSION}) + +target_link_libraries(nepomukqueryclient + nepomukquery + ${QT_QTCORE_LIBRARY} + ${KDE4_KDECORE_LIBS} + ${SOPRANO_LIBRARIES} + ) + +install(TARGETS nepomukqueryclient ${INSTALL_TARGETS_DEFAULT_ARGS}) + +install(FILES + nepomukqueryclient_export.h + queryserviceclient.h + DESTINATION ${INCLUDE_INSTALL_DIR}/nepomuk +) diff --git a/nepomukqueryclient/nepomukqueryclient_export.h b/nepomukqueryclient/nepomukqueryclient_export.h new file mode 100644 index 000000000..d53bc2698 --- /dev/null +++ b/nepomukqueryclient/nepomukqueryclient_export.h @@ -0,0 +1,36 @@ +/* This file is part of the KDE project + Copyright (C) 2007 David Faure + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This 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 NEPOMUKQUERYCLIENT_EXPORT_H +#define NEPOMUKQUERYCLIENT_EXPORT_H + +/* needed for KDE_EXPORT and KDE_IMPORT macros */ +#include + +#ifndef NEPOMUKQUERYCLIENT_EXPORT +# if defined(MAKE_NEPOMUKQUERYCLIENT_LIB) + /* We are building this library */ +# define NEPOMUKQUERYCLIENT_EXPORT KDE_EXPORT +# else + /* We are using this library */ +# define NEPOMUKQUERYCLIENT_EXPORT KDE_IMPORT +# endif +#endif + +#endif diff --git a/nepomukqueryclient/org.kde.nepomuk.Query.xml b/nepomukqueryclient/org.kde.nepomuk.Query.xml new file mode 100644 index 000000000..71b18862d --- /dev/null +++ b/nepomukqueryclient/org.kde.nepomuk.Query.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + diff --git a/nepomukqueryclient/org.kde.nepomuk.QueryService.xml b/nepomukqueryclient/org.kde.nepomuk.QueryService.xml new file mode 100644 index 000000000..180c6bb78 --- /dev/null +++ b/nepomukqueryclient/org.kde.nepomuk.QueryService.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + diff --git a/nepomukqueryclient/querymetatype.h b/nepomukqueryclient/querymetatype.h new file mode 100644 index 000000000..2c6d39ac6 --- /dev/null +++ b/nepomukqueryclient/querymetatype.h @@ -0,0 +1,8 @@ +/* + * This file looks very weird but is the only way to get the Query metatype + * into the service interface when generated via qdbusxml2cpp. + */ + +#include "query.h" + +Q_DECLARE_METATYPE(Nepomuk::Search::Query) diff --git a/nepomukqueryclient/queryserviceclient.cpp b/nepomukqueryclient/queryserviceclient.cpp new file mode 100644 index 000000000..95bc9b0d7 --- /dev/null +++ b/nepomukqueryclient/queryserviceclient.cpp @@ -0,0 +1,232 @@ +/* + Copyright (c) 2008 Sebastian Trueg + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "queryserviceclient.h" +#include "dbusoperators.h" +#include "result.h" +#include "query.h" +#include "queryserviceinterface.h" +#include "queryinterface.h" + +#include +#include +#include +#include + +#include +#include + +#include +#include + + +namespace { + /** + * Each thread needs its own QDBusConnection. We do it the very easy + * way and just create a new connection for each client + * Why does Qt not handle this automatically? + */ + class QDBusConnectionPerThreadHelper + { + public: + QDBusConnectionPerThreadHelper() + : m_counter( 0 ) { + } + + QDBusConnection newConnection() { + QMutexLocker lock( &m_mutex ); + return QDBusConnection::connectToBus( QDBusConnection::SessionBus, + QString("NepomukQueryServiceConnection%1").arg(++m_counter) ); + } + + private: + int m_counter; + QMutex m_mutex; + }; + + K_GLOBAL_STATIC( QDBusConnectionPerThreadHelper, s_globalDBusConnectionPerThreadHelper ) +} + + +class Nepomuk::Search::QueryServiceClient::Private +{ +public: + Private() + : queryServiceInterface( 0 ), + queryInterface( 0 ), + dbusConnection( s_globalDBusConnectionPerThreadHelper->newConnection() ), + loop( 0 ) { + } + + void _k_entriesRemoved( const QStringList& ); + void _k_finishedListing(); + bool handleQueryReply( QDBusReply reply ); + + org::kde::nepomuk::QueryService* queryServiceInterface; + org::kde::nepomuk::Query* queryInterface; + + QueryServiceClient* q; + + QDBusConnection dbusConnection; + + QEventLoop* loop; +}; + + +void Nepomuk::Search::QueryServiceClient::Private::_k_entriesRemoved( const QStringList& uris ) +{ + QList ul; + foreach( const QString& s, uris ) { + ul.append( QUrl( s ) ); + } + emit q->entriesRemoved( ul ); +} + + +void Nepomuk::Search::QueryServiceClient::Private::_k_finishedListing() +{ + emit q->finishedListing(); + if( loop ) { + q->close(); + } +} + + +bool Nepomuk::Search::QueryServiceClient::Private::handleQueryReply( QDBusReply r ) +{ + if ( r.isValid() ) { + queryInterface = new org::kde::nepomuk::Query( queryServiceInterface->service(), + r.value().path(), + dbusConnection ); + connect( queryInterface, SIGNAL( newEntries( QList ) ), + q, SIGNAL( newEntries( QList ) ) ); + connect( queryInterface, SIGNAL( entriesRemoved( QStringList ) ), + q, SLOT( _k_entriesRemoved( QStringList ) ) ); + connect( queryInterface, SIGNAL( finishedListing() ), + q, SLOT( _k_finishedListing() ) ); + // run the listing async in case the event loop below is the only one we have + // and we need it to handle the signals and list returns results immediately + QTimer::singleShot( 0, queryInterface, SLOT(list()) ); + return true; + } + else { + kDebug() << "Query failed:" << r.error().message(); + return false; + } +} + + +Nepomuk::Search::QueryServiceClient::QueryServiceClient( QObject* parent ) + : QObject( parent ), + d( new Private() ) +{ + d->q = this; + + Nepomuk::Search::registerDBusTypes(); + + // we use our own connection to be thread-safe + d->queryServiceInterface = new org::kde::nepomuk::QueryService( "org.kde.nepomuk.services.nepomukqueryservice", + "/nepomukqueryservice", + d->dbusConnection ); +} + + +Nepomuk::Search::QueryServiceClient::~QueryServiceClient() +{ + close(); + delete d; +} + + +bool Nepomuk::Search::QueryServiceClient::query( const QString& query ) +{ + close(); + + if ( d->queryServiceInterface->isValid() ) { + return d->handleQueryReply( d->queryServiceInterface->query( query, QStringList() ) ); + } + else { + kDebug() << "Could not contact query service."; + return false; + } +} + + +bool Nepomuk::Search::QueryServiceClient::query( const Query& query ) +{ + close(); + + if ( d->queryServiceInterface->isValid() ) { + return d->handleQueryReply( d->queryServiceInterface->query( query ) ); + } + else { + kDebug() << "Could not contact query service."; + return false; + } +} + + +bool Nepomuk::Search::QueryServiceClient::blockingQuery( const QString& q ) +{ + if( query( q ) ) { + QEventLoop loop; + d->loop = &loop; + loop.exec(); + d->loop = 0; + return true; + } + else { + return false; + } +} + + +bool Nepomuk::Search::QueryServiceClient::blockingQuery( const Query& q ) +{ + if( query( q ) ) { + QEventLoop loop; + d->loop = &loop; + loop.exec(); + d->loop = 0; + return true; + } + else { + return false; + } +} + + +void Nepomuk::Search::QueryServiceClient::close() +{ + if ( d->queryInterface ) { + kDebug(); + d->queryInterface->close(); + delete d->queryInterface; + d->queryInterface = 0; + if( d->loop ) + d->loop->exit(); + } +} + + +bool Nepomuk::Search::QueryServiceClient::serviceAvailable() +{ + return QDBusConnection::sessionBus().interface()->isServiceRegistered( "org.kde.nepomuk.services.nepomukqueryservice" ); +} + +#include "queryserviceclient.moc" diff --git a/nepomukqueryclient/queryserviceclient.h b/nepomukqueryclient/queryserviceclient.h new file mode 100644 index 000000000..8410ac350 --- /dev/null +++ b/nepomukqueryclient/queryserviceclient.h @@ -0,0 +1,161 @@ +/* + Copyright (c) 2008 Sebastian Trueg + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef _NEPOMUK_QUERY_SERVICE_CLIENT_H_ +#define _NEPOMUK_QUERY_SERVICE_CLIENT_H_ + +#include + +#include "nepomukqueryclient_export.h" + +class QUrl; + +namespace Nepomuk { + namespace Search { + + class Result; + class Query; + + /** + * \class QueryServiceClient queryserviceclient.h Nepomuk/Search/QueryServiceClient + * + * \brief Convenience frontend to the %Nepomuk Query DBus Service + * + * The QueryServiceClient provides an easy way to access the %Nepomuk Query Service + * without having to deal with any communication details. By default it monitors + * queries for changes. + * + * Usage is simple: Create an instance of the client for each search you want to + * track. Once instance may also be reused for subsequent queries if further updates + * of the persistent query are not necessary. + * + * \author Sebastian Trueg + */ + class NEPOMUKQUERYCLIENT_EXPORT QueryServiceClient : public QObject + { + Q_OBJECT + + public: + /** + * Create a new QueryServiceClient instance. + */ + QueryServiceClient( QObject* parent = 0 ); + + /** + * Desctructor. Closes the query. + */ + ~QueryServiceClient(); + + /** + * Check if the service is running. + * \return \p true if the Nepomuk query service is running and could + * be contacted via DBus, \p false otherwise + */ + static bool serviceAvailable(); + + public Q_SLOTS: + /** + * Start a query using the Nepomuk user query language. + * + * Results will be reported via newEntries. All results + * have been reported once finishedListing has been emitted. + * + * \return \p true if the query service was found and the query + * was started. \p false otherwise. + * + * \sa QueryParser + */ + bool query( const QString& query ); + + /** + * Start a query. + * + * Results will be reported via newEntries. All results + * have been reported once finishedListing has been emitted. + * + * \return \p true if the query service was found and the query + * was started. \p false otherwise. + */ + bool query( const Query& query ); + + /** + * Start a query using the Nepomuk user query language. + * + * Results will be reported as with query(const QString&) + * but a local event loop will be started to block the method + * call until all results have been listed. + * + * The client will be closed after the initial listing. Thus, + * changes to results will not be reported as it is the case + * with the non-blocking methods. + * + * \return \p true if the query service was found and the query + * was started. \p false otherwise. + * + * \sa query(const QString&), close() + */ + bool blockingQuery( const QString& query ); + + /** + * \overload + * + * \sa query(const Query&) + */ + bool blockingQuery( const Query& query ); + + /** + * Close the client, thus stop to monitor the query + * for changes. Without closing the client it will continue + * signalling changes to the results. + * + * This will also make any blockingQuery return immediately. + */ + void close(); + + Q_SIGNALS: + /** + * Emitted for new search results. This signal is emitted both + * for the initial listing and for changes to the search. + */ + void newEntries( const QList& entries ); + + /** + * Emitted if the search results changed when monitoring a query. + * \param entries A list of resource URIs identifying the resources + * that dropped out of the query results. + */ + void entriesRemoved( const QList& entries ); + + /** + * Emitted when the initial listing has been finished, ie. if all + * results have been reported via newEntries. If no further updates + * are necessary the client should be closed now. + */ + void finishedListing(); + + private: + class Private; + Private* const d; + + Q_PRIVATE_SLOT( d, void _k_entriesRemoved( const QStringList& ) ) + Q_PRIVATE_SLOT( d, void _k_finishedListing() ) + }; + } +} + +#endif diff --git a/plasma/CMakeLists.txt b/plasma/CMakeLists.txt new file mode 100644 index 000000000..8c850b99b --- /dev/null +++ b/plasma/CMakeLists.txt @@ -0,0 +1,299 @@ +find_package(Nepomuk REQUIRED) +include (KDE4Defaults) +include(NepomukMacros) + +include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${KDEBASE_WORKSPACE_SOURCE_DIR}/libs ${CMAKE_CURRENT_SOURCE_DIR}/.. ${KDE4_INCLUDES}) +if(QT_QTOPENGL_FOUND AND OPENGL_FOUND) + include_directories(${OPENGL_INCLUDE_DIR}) +endif(QT_QTOPENGL_FOUND AND OPENGL_FOUND) + +add_subdirectory(tests) +add_definitions(-DKDE_DEFAULT_DEBUG_AREA=1209) + +########### next target ############### + +set(plasmagik_SRCS + packagemetadata.cpp + packagestructure.cpp + package.cpp + ) + +set(plasma_LIB_SRCS + ${plasmagik_SRCS} + abstractrunner.cpp + animationdriver.cpp + animator.cpp + applet.cpp + configloader.cpp + containment.cpp + context.cpp + corona.cpp + datacontainer.cpp + dataengine.cpp + dataenginemanager.cpp + delegate.cpp + dialog.cpp + extender.cpp + extenderitem.cpp + paintutils.cpp + framesvg.cpp + plasma.cpp + popupapplet.cpp + private/applethandle.cpp + private/datacontainer_p.cpp + private/desktoptoolbox.cpp + private/extenderapplet.cpp + private/nativetabbar.cpp + private/packages.cpp + private/paneltoolbox.cpp + private/style.cpp + private/toolbox.cpp + private/tooltip.cpp + private/windowpreview.cpp + querymatch.cpp + runnercontext.cpp + runnermanager.cpp + scripting/appletscript.cpp + scripting/dataenginescript.cpp + scripting/runnerscript.cpp + scripting/scriptengine.cpp + scripting/uiloader.cpp + service.cpp + servicejob.cpp + svg.cpp + theme.cpp + tooltipcontent.cpp + tooltipmanager.cpp + version.cpp + view.cpp + wallpaper.cpp + widgets/checkbox.cpp + widgets/combobox.cpp + widgets/flashinglabel.cpp + widgets/frame.cpp + widgets/groupbox.cpp + widgets/iconwidget.cpp + widgets/label.cpp + widgets/lineedit.cpp + widgets/meter.cpp + widgets/pushbutton.cpp + widgets/radiobutton.cpp + widgets/scrollbar.cpp + widgets/signalplotter.cpp + widgets/slider.cpp + widgets/busywidget.cpp + widgets/svgwidget.cpp + widgets/tabbar.cpp + widgets/treeview.cpp + widgets/textedit.cpp + widgets/webview.cpp +) + +#NEPOMUK_GENERATE_FROM_ONTOLOGY( +# nwc.nrl +# ${metadata_test_BINARY_DIR} +# TEST_HEADERS +# TEST_SOURCES +# TEST_INCLUDES +#) + +if(QT_QTOPENGL_FOUND AND OPENGL_FOUND) +MESSAGE(STATUS "Adding support for OpenGL applets to libplasma") +set(plasma_LIB_SRCS + ${plasma_LIB_SRCS} + glapplet.cpp) +endif(QT_QTOPENGL_FOUND AND OPENGL_FOUND) + +kde4_add_library(plasma SHARED ${plasma_LIB_SRCS}) + +target_link_libraries(plasma ${KDE4_KIO_LIBS} ${KDE4_KFILE_LIBS} ${KDE4_KNEWSTUFF2_LIBS} + ${QT_QTUITOOLS_LIBRARY} ${QT_QTWEBKIT_LIBRARY} + ${KDE4_THREADWEAVER_LIBRARIES} ${KDE4_SOLID_LIBS} ${X11_LIBRARIES}) +if(DL_LIBRARY) +target_link_libraries(plasma ${DL_LIBRARY}) +endif(DL_LIBRARY) + +if(QT_QTOPENGL_FOUND AND OPENGL_FOUND) + target_link_libraries(plasma ${QT_QTOPENGL_LIBRARY} ${OPENGL_gl_LIBRARY}) +endif(QT_QTOPENGL_FOUND AND OPENGL_FOUND) + +set_target_properties(plasma PROPERTIES + VERSION 3.0.0 + SOVERSION 3 + ${KDE4_DISABLE_PROPERTY_}LINK_INTERFACE_LIBRARIES "${KDE4_KDEUI_LIBS}" + ) + +install(TARGETS plasma ${INSTALL_TARGETS_DEFAULT_ARGS}) + + +########### install files ############### + +set(plasmagik_HEADERS + packagemetadata.h + packagestructure.h + package.h + ) + +install(FILES ${plasmagik_HEADERS} DESTINATION ${INCLUDE_INSTALL_DIR}/plasma/ COMPONENT Devel) + +set(plasma_LIB_INCLUDES + abstractrunner.h + animationdriver.h + animator.h + applet.h + configloader.h + containment.h + context.h + corona.h + datacontainer.h + dataengine.h + dataenginemanager.h + delegate.h + dialog.h + extender.h + extenderitem.h + paintutils.h + framesvg.h + plasma.h + plasma_export.h + popupapplet.h + querymatch.h + runnercontext.h + runnermanager.h + service.h + servicejob.h + svg.h + theme.h + tooltipcontent.h + tooltipmanager.h + tooltipmanager.h + version.h + view.h + wallpaper.h) + +if(QT_QTOPENGL_FOUND AND OPENGL_FOUND) +set(plasma_LIB_INCLUDES + ${plasma_LIB_INCLUDES} + glapplet.h) +endif(QT_QTOPENGL_FOUND AND OPENGL_FOUND) + +install(FILES + ${plasma_LIB_INCLUDES} + DESTINATION ${INCLUDE_INSTALL_DIR}/plasma COMPONENT Devel) + +install(FILES + widgets/checkbox.h + widgets/combobox.h + widgets/flashinglabel.h + widgets/frame.h + widgets/groupbox.h + widgets/iconwidget.h + widgets/label.h + widgets/lineedit.h + widgets/meter.h + widgets/pushbutton.h + widgets/radiobutton.h + widgets/scrollbar.h + widgets/signalplotter.h + widgets/slider.h + widgets/busywidget.h + widgets/svgwidget.h + widgets/tabbar.h + widgets/treeview.h + widgets/textedit.h + widgets/webview.h + DESTINATION ${INCLUDE_INSTALL_DIR}/plasma/widgets COMPONENT Devel) + +install(FILES + scripting/appletscript.h + scripting/dataenginescript.h + scripting/runnerscript.h + scripting/scriptengine.h + scripting/uiloader.h + DESTINATION ${INCLUDE_INSTALL_DIR}/plasma/scripting COMPONENT Devel) + + +install(FILES +includes/AbstractRunner +includes/AnimationDriver +includes/Animator +includes/Applet +includes/AppletScript +includes/CheckBox +includes/ComboBox +includes/ConfigLoader +includes/Containment +includes/Context +includes/Corona +includes/DataContainer +includes/DataEngine +includes/DataEngineManager +includes/DataEngineScript +includes/Delegate +includes/Dialog +includes/Extender +includes/ExtenderItem +includes/FlashingLabel +includes/Frame +includes/FrameSvg +includes/GroupBox +includes/IconWidget +includes/Label +includes/LineEdit +includes/Meter +includes/Package +includes/PackageMetadata +includes/PackageStructure +includes/PaintUtils +includes/Plasma +includes/PopupApplet +includes/PushButton +includes/QueryMatch +includes/RadioButton +includes/RunnerContext +includes/RunnerManager +includes/RunnerScript +includes/ScriptEngine +includes/ScrollBar +includes/Service +includes/ServiceJob +includes/SignalPlotter +includes/Slider +includes/BusyWidget +includes/Svg +includes/SvgWidget +includes/TabBar +includes/TextEdit +includes/ToolTipManager +includes/Theme +includes/TreeView +includes/UiLoader +includes/View +includes/Version +includes/Wallpaper +includes/WebView +DESTINATION ${INCLUDE_INSTALL_DIR}/KDE/Plasma COMPONENT Devel) + +if(QT_QTOPENGL_FOUND AND OPENGL_FOUND) + install(FILES + includes/GLApplet + DESTINATION ${INCLUDE_INSTALL_DIR}/KDE/Plasma COMPONENT Devel) +endif(QT_QTOPENGL_FOUND AND OPENGL_FOUND) + +install(FILES + servicetypes/plasma-animator.desktop + servicetypes/plasma-applet.desktop + servicetypes/plasma-containment.desktop + servicetypes/plasma-dataengine.desktop + servicetypes/plasma-packagestructure.desktop + servicetypes/plasma-runner.desktop + servicetypes/plasma-scriptengine.desktop + servicetypes/plasma-wallpaper.desktop + DESTINATION ${SERVICETYPES_INSTALL_DIR}) + +install(FILES + servicetypes/plasma-applet-extenderapplet.desktop + DESTINATION ${SERVICES_INSTALL_DIR}) + +install(FILES scripting/plasmoids.knsrc DESTINATION ${CONFIG_INSTALL_DIR}) + diff --git a/plasma/Mainpage.dox b/plasma/Mainpage.dox new file mode 100644 index 000000000..225e338fb --- /dev/null +++ b/plasma/Mainpage.dox @@ -0,0 +1,100 @@ +/** @mainpage Plasma libraries + +libplasma is the core of the Plasma desktop. It provides a framework of graphical +widgets (Plasma::Applet) that can be organised into managed groupings +(Plasma::Containment), such as a desktop or panel. It also provides a data +abstraction layer (Plasma::DataEngine) and a corresponding service interaction +layer (Plasma::Service) to make implementing widgets easier and a +system of callouts (Plasma::AbstractRunner) that provide responses to queries, +from running an application to performing a quick calculation. + +The Qt Graphics View +framework and the KDE +libraries provide the underpinning for libplasma. As a result, it should +work anywhere that Qt and KDE do. + +Although libplasma is developed for the use of Plasma, the new desktop shell in +KDE 4, it is general enough to be useful in other applications. +Amarok is already using it for its context +view, allowing for pluggable widgets to display and interact with the music +collection, such as "current track" and "tag cloud" widgets. + +libplasma itself only provides a framework, and the widgets, containments, +data engines and runners are all implemented as plugins. However, the framework +is designed to make implementing these plugins as easy as possible, including +providing scripting support. Also, infrastructure such as a dialog to install +new widgets and even download them from the web (Plasma::AppletBrowser) is also +included. + +Other important classes are: + + - Plasma::Corona: the canvas that containments are placed on + - Plasma::View: a QWidget for displaying a containment + - Plasma::Theme: provides theming support + - Plasma::Animator: provides animations for things like elements appearing + and disappearing + - Plasma::Delegate: provides an item delegate for Qt's + Model / + View framework for menu items. + - Plasma::ToolTipManager: allows widgets have (themed) tooltips displayed when the + mouse is hovered over them + - Plasma::Dialog: displays a themed application dialog + - Plasma::Extender: provides detachable sections to Plasma::Applet + - Plasma::GLApplet: provides an OpneGL-rendered Plasma::Applet + - Plasma::PackageStructure: provides descriptions of packages containing plugins + for libplasma + - Plasma::PopupApplet: provides a simple way of implementing a Plasma::Applet + consisting of an icon that shows a popup when clicked + - Plasma::Svg and Plasma::FrameSvg: provides themable, cached SVGs + - Plasma::Wallpaper: provides pluggable backgrounds for containments + - Plasma::AppletScript, Plasma::DataEngineScript, Plasma::RunnerScript and + Plasma::ScriptEngine: provide scripting interfaces for plugins + - Various themed QGraphicsWidgets for use in creating a Plasma::Applet + + +The +Plasma tutorials +on TechBase provide a good introduction to writing plugins, such as widgets and +data engines, for libplasma-based applications. + +@authors +Aaron Seigo \
    +Alessandro Diaferia \
    +Alex Merry \
    +Alexander Wiedenbruch \
    +Alexis Ménard \
    +André Duffeck \
    +Andrew Lake \
    +Bertjan Broeksema \
    +Chani Armitage \
    +Davide Bettio \
    +Dan Meltzer \
    +Fredrik Höglund \
    +Ivan Cukic \
    +John Tapsell \
    +Jordi Polo \
    +Kevin Ottens \
    +Montel Laurent \ +Marco Martin \
    +Matt Broadstone \
    +Petri Damsten \
    +Rafael Fernández López \
    +Riccardo Iaconelli \
    +Richard J. Moore \
    +Rob Scheepmaker \
    +Robert Knight \
    +Sebastian Kuegler \
    +Siraj Razick \
    +Zack Rusin \ + +@maintainers +Aaron Seigo \ + +@licenses +@lgpl + +*/ + +// DOXYGEN_SET_PROJECT_NAME = libplasma +// DOXYGEN_SET_RECURSIVE = YES +// vim:ts=4:sw=4:expandtab:filetype=doxygen diff --git a/Messages.sh b/plasma/Messages.sh similarity index 100% rename from Messages.sh rename to plasma/Messages.sh diff --git a/README b/plasma/README similarity index 100% rename from README rename to plasma/README diff --git a/abstractrunner.cpp b/plasma/abstractrunner.cpp similarity index 100% rename from abstractrunner.cpp rename to plasma/abstractrunner.cpp diff --git a/abstractrunner.h b/plasma/abstractrunner.h similarity index 100% rename from abstractrunner.h rename to plasma/abstractrunner.h diff --git a/animationdriver.cpp b/plasma/animationdriver.cpp similarity index 100% rename from animationdriver.cpp rename to plasma/animationdriver.cpp diff --git a/animationdriver.h b/plasma/animationdriver.h similarity index 100% rename from animationdriver.h rename to plasma/animationdriver.h diff --git a/animator.cpp b/plasma/animator.cpp similarity index 100% rename from animator.cpp rename to plasma/animator.cpp diff --git a/animator.h b/plasma/animator.h similarity index 100% rename from animator.h rename to plasma/animator.h diff --git a/applet.cpp b/plasma/applet.cpp similarity index 100% rename from applet.cpp rename to plasma/applet.cpp diff --git a/applet.h b/plasma/applet.h similarity index 100% rename from applet.h rename to plasma/applet.h diff --git a/configloader.cpp b/plasma/configloader.cpp similarity index 100% rename from configloader.cpp rename to plasma/configloader.cpp diff --git a/configloader.h b/plasma/configloader.h similarity index 100% rename from configloader.h rename to plasma/configloader.h diff --git a/containment.cpp b/plasma/containment.cpp similarity index 100% rename from containment.cpp rename to plasma/containment.cpp diff --git a/containment.h b/plasma/containment.h similarity index 100% rename from containment.h rename to plasma/containment.h diff --git a/context.cpp b/plasma/context.cpp similarity index 100% rename from context.cpp rename to plasma/context.cpp diff --git a/context.h b/plasma/context.h similarity index 100% rename from context.h rename to plasma/context.h diff --git a/corona.cpp b/plasma/corona.cpp similarity index 100% rename from corona.cpp rename to plasma/corona.cpp diff --git a/corona.h b/plasma/corona.h similarity index 100% rename from corona.h rename to plasma/corona.h diff --git a/datacontainer.cpp b/plasma/datacontainer.cpp similarity index 100% rename from datacontainer.cpp rename to plasma/datacontainer.cpp diff --git a/datacontainer.h b/plasma/datacontainer.h similarity index 100% rename from datacontainer.h rename to plasma/datacontainer.h diff --git a/dataengine.cpp b/plasma/dataengine.cpp similarity index 100% rename from dataengine.cpp rename to plasma/dataengine.cpp diff --git a/dataengine.h b/plasma/dataengine.h similarity index 100% rename from dataengine.h rename to plasma/dataengine.h diff --git a/dataenginemanager.cpp b/plasma/dataenginemanager.cpp similarity index 100% rename from dataenginemanager.cpp rename to plasma/dataenginemanager.cpp diff --git a/dataenginemanager.h b/plasma/dataenginemanager.h similarity index 100% rename from dataenginemanager.h rename to plasma/dataenginemanager.h diff --git a/delegate.cpp b/plasma/delegate.cpp similarity index 100% rename from delegate.cpp rename to plasma/delegate.cpp diff --git a/delegate.h b/plasma/delegate.h similarity index 100% rename from delegate.h rename to plasma/delegate.h diff --git a/dialog.cpp b/plasma/dialog.cpp similarity index 100% rename from dialog.cpp rename to plasma/dialog.cpp diff --git a/dialog.h b/plasma/dialog.h similarity index 100% rename from dialog.h rename to plasma/dialog.h diff --git a/effects/blur.cpp b/plasma/effects/blur.cpp similarity index 100% rename from effects/blur.cpp rename to plasma/effects/blur.cpp diff --git a/extender.cpp b/plasma/extender.cpp similarity index 100% rename from extender.cpp rename to plasma/extender.cpp diff --git a/extender.h b/plasma/extender.h similarity index 100% rename from extender.h rename to plasma/extender.h diff --git a/extenderitem.cpp b/plasma/extenderitem.cpp similarity index 100% rename from extenderitem.cpp rename to plasma/extenderitem.cpp diff --git a/extenderitem.h b/plasma/extenderitem.h similarity index 100% rename from extenderitem.h rename to plasma/extenderitem.h diff --git a/framesvg.cpp b/plasma/framesvg.cpp similarity index 100% rename from framesvg.cpp rename to plasma/framesvg.cpp diff --git a/framesvg.h b/plasma/framesvg.h similarity index 100% rename from framesvg.h rename to plasma/framesvg.h diff --git a/glapplet.cpp b/plasma/glapplet.cpp similarity index 100% rename from glapplet.cpp rename to plasma/glapplet.cpp diff --git a/glapplet.h b/plasma/glapplet.h similarity index 100% rename from glapplet.h rename to plasma/glapplet.h diff --git a/includes/AbstractRunner b/plasma/includes/AbstractRunner similarity index 100% rename from includes/AbstractRunner rename to plasma/includes/AbstractRunner diff --git a/includes/AnimationDriver b/plasma/includes/AnimationDriver similarity index 100% rename from includes/AnimationDriver rename to plasma/includes/AnimationDriver diff --git a/includes/Animator b/plasma/includes/Animator similarity index 100% rename from includes/Animator rename to plasma/includes/Animator diff --git a/includes/Applet b/plasma/includes/Applet similarity index 100% rename from includes/Applet rename to plasma/includes/Applet diff --git a/includes/AppletScript b/plasma/includes/AppletScript similarity index 100% rename from includes/AppletScript rename to plasma/includes/AppletScript diff --git a/includes/BusyWidget b/plasma/includes/BusyWidget similarity index 100% rename from includes/BusyWidget rename to plasma/includes/BusyWidget diff --git a/includes/CheckBox b/plasma/includes/CheckBox similarity index 100% rename from includes/CheckBox rename to plasma/includes/CheckBox diff --git a/includes/ComboBox b/plasma/includes/ComboBox similarity index 100% rename from includes/ComboBox rename to plasma/includes/ComboBox diff --git a/includes/ConfigLoader b/plasma/includes/ConfigLoader similarity index 100% rename from includes/ConfigLoader rename to plasma/includes/ConfigLoader diff --git a/includes/Containment b/plasma/includes/Containment similarity index 100% rename from includes/Containment rename to plasma/includes/Containment diff --git a/includes/Context b/plasma/includes/Context similarity index 100% rename from includes/Context rename to plasma/includes/Context diff --git a/includes/Corona b/plasma/includes/Corona similarity index 100% rename from includes/Corona rename to plasma/includes/Corona diff --git a/includes/DataContainer b/plasma/includes/DataContainer similarity index 100% rename from includes/DataContainer rename to plasma/includes/DataContainer diff --git a/includes/DataEngine b/plasma/includes/DataEngine similarity index 100% rename from includes/DataEngine rename to plasma/includes/DataEngine diff --git a/includes/DataEngineManager b/plasma/includes/DataEngineManager similarity index 100% rename from includes/DataEngineManager rename to plasma/includes/DataEngineManager diff --git a/includes/DataEngineScript b/plasma/includes/DataEngineScript similarity index 100% rename from includes/DataEngineScript rename to plasma/includes/DataEngineScript diff --git a/includes/Delegate b/plasma/includes/Delegate similarity index 100% rename from includes/Delegate rename to plasma/includes/Delegate diff --git a/includes/Dialog b/plasma/includes/Dialog similarity index 100% rename from includes/Dialog rename to plasma/includes/Dialog diff --git a/includes/Extender b/plasma/includes/Extender similarity index 100% rename from includes/Extender rename to plasma/includes/Extender diff --git a/includes/ExtenderItem b/plasma/includes/ExtenderItem similarity index 100% rename from includes/ExtenderItem rename to plasma/includes/ExtenderItem diff --git a/includes/FlashingLabel b/plasma/includes/FlashingLabel similarity index 100% rename from includes/FlashingLabel rename to plasma/includes/FlashingLabel diff --git a/includes/Frame b/plasma/includes/Frame similarity index 100% rename from includes/Frame rename to plasma/includes/Frame diff --git a/includes/FrameSvg b/plasma/includes/FrameSvg similarity index 100% rename from includes/FrameSvg rename to plasma/includes/FrameSvg diff --git a/includes/GLApplet b/plasma/includes/GLApplet similarity index 100% rename from includes/GLApplet rename to plasma/includes/GLApplet diff --git a/includes/GroupBox b/plasma/includes/GroupBox similarity index 100% rename from includes/GroupBox rename to plasma/includes/GroupBox diff --git a/includes/IconWidget b/plasma/includes/IconWidget similarity index 100% rename from includes/IconWidget rename to plasma/includes/IconWidget diff --git a/includes/Label b/plasma/includes/Label similarity index 100% rename from includes/Label rename to plasma/includes/Label diff --git a/includes/LineEdit b/plasma/includes/LineEdit similarity index 100% rename from includes/LineEdit rename to plasma/includes/LineEdit diff --git a/includes/Meter b/plasma/includes/Meter similarity index 100% rename from includes/Meter rename to plasma/includes/Meter diff --git a/includes/Package b/plasma/includes/Package similarity index 100% rename from includes/Package rename to plasma/includes/Package diff --git a/includes/PackageMetadata b/plasma/includes/PackageMetadata similarity index 100% rename from includes/PackageMetadata rename to plasma/includes/PackageMetadata diff --git a/includes/PackageStructure b/plasma/includes/PackageStructure similarity index 100% rename from includes/PackageStructure rename to plasma/includes/PackageStructure diff --git a/includes/PaintUtils b/plasma/includes/PaintUtils similarity index 100% rename from includes/PaintUtils rename to plasma/includes/PaintUtils diff --git a/includes/Plasma b/plasma/includes/Plasma similarity index 100% rename from includes/Plasma rename to plasma/includes/Plasma diff --git a/includes/PopupApplet b/plasma/includes/PopupApplet similarity index 100% rename from includes/PopupApplet rename to plasma/includes/PopupApplet diff --git a/includes/PushButton b/plasma/includes/PushButton similarity index 100% rename from includes/PushButton rename to plasma/includes/PushButton diff --git a/includes/QueryMatch b/plasma/includes/QueryMatch similarity index 100% rename from includes/QueryMatch rename to plasma/includes/QueryMatch diff --git a/includes/RadioButton b/plasma/includes/RadioButton similarity index 100% rename from includes/RadioButton rename to plasma/includes/RadioButton diff --git a/includes/RunnerContext b/plasma/includes/RunnerContext similarity index 100% rename from includes/RunnerContext rename to plasma/includes/RunnerContext diff --git a/includes/RunnerManager b/plasma/includes/RunnerManager similarity index 100% rename from includes/RunnerManager rename to plasma/includes/RunnerManager diff --git a/includes/RunnerScript b/plasma/includes/RunnerScript similarity index 100% rename from includes/RunnerScript rename to plasma/includes/RunnerScript diff --git a/includes/ScriptEngine b/plasma/includes/ScriptEngine similarity index 100% rename from includes/ScriptEngine rename to plasma/includes/ScriptEngine diff --git a/includes/ScrollBar b/plasma/includes/ScrollBar similarity index 100% rename from includes/ScrollBar rename to plasma/includes/ScrollBar diff --git a/includes/Service b/plasma/includes/Service similarity index 100% rename from includes/Service rename to plasma/includes/Service diff --git a/includes/ServiceJob b/plasma/includes/ServiceJob similarity index 100% rename from includes/ServiceJob rename to plasma/includes/ServiceJob diff --git a/includes/SignalPlotter b/plasma/includes/SignalPlotter similarity index 100% rename from includes/SignalPlotter rename to plasma/includes/SignalPlotter diff --git a/includes/Slider b/plasma/includes/Slider similarity index 100% rename from includes/Slider rename to plasma/includes/Slider diff --git a/includes/Svg b/plasma/includes/Svg similarity index 100% rename from includes/Svg rename to plasma/includes/Svg diff --git a/includes/SvgWidget b/plasma/includes/SvgWidget similarity index 100% rename from includes/SvgWidget rename to plasma/includes/SvgWidget diff --git a/includes/TabBar b/plasma/includes/TabBar similarity index 100% rename from includes/TabBar rename to plasma/includes/TabBar diff --git a/includes/TextEdit b/plasma/includes/TextEdit similarity index 100% rename from includes/TextEdit rename to plasma/includes/TextEdit diff --git a/includes/Theme b/plasma/includes/Theme similarity index 100% rename from includes/Theme rename to plasma/includes/Theme diff --git a/includes/ToolTipManager b/plasma/includes/ToolTipManager similarity index 100% rename from includes/ToolTipManager rename to plasma/includes/ToolTipManager diff --git a/includes/TreeView b/plasma/includes/TreeView similarity index 100% rename from includes/TreeView rename to plasma/includes/TreeView diff --git a/includes/UiLoader b/plasma/includes/UiLoader similarity index 100% rename from includes/UiLoader rename to plasma/includes/UiLoader diff --git a/includes/Version b/plasma/includes/Version similarity index 100% rename from includes/Version rename to plasma/includes/Version diff --git a/includes/View b/plasma/includes/View similarity index 100% rename from includes/View rename to plasma/includes/View diff --git a/includes/Wallpaper b/plasma/includes/Wallpaper similarity index 100% rename from includes/Wallpaper rename to plasma/includes/Wallpaper diff --git a/includes/WebView b/plasma/includes/WebView similarity index 100% rename from includes/WebView rename to plasma/includes/WebView diff --git a/package.cpp b/plasma/package.cpp similarity index 100% rename from package.cpp rename to plasma/package.cpp diff --git a/package.h b/plasma/package.h similarity index 100% rename from package.h rename to plasma/package.h diff --git a/packagemetadata.cpp b/plasma/packagemetadata.cpp similarity index 100% rename from packagemetadata.cpp rename to plasma/packagemetadata.cpp diff --git a/packagemetadata.h b/plasma/packagemetadata.h similarity index 100% rename from packagemetadata.h rename to plasma/packagemetadata.h diff --git a/packagestructure.cpp b/plasma/packagestructure.cpp similarity index 100% rename from packagestructure.cpp rename to plasma/packagestructure.cpp diff --git a/packagestructure.h b/plasma/packagestructure.h similarity index 100% rename from packagestructure.h rename to plasma/packagestructure.h diff --git a/paintutils.cpp b/plasma/paintutils.cpp similarity index 100% rename from paintutils.cpp rename to plasma/paintutils.cpp diff --git a/paintutils.h b/plasma/paintutils.h similarity index 100% rename from paintutils.h rename to plasma/paintutils.h diff --git a/plasma.cpp b/plasma/plasma.cpp similarity index 100% rename from plasma.cpp rename to plasma/plasma.cpp diff --git a/plasma.h b/plasma/plasma.h similarity index 100% rename from plasma.h rename to plasma/plasma.h diff --git a/plasma_export.h b/plasma/plasma_export.h similarity index 100% rename from plasma_export.h rename to plasma/plasma_export.h diff --git a/popupapplet.cpp b/plasma/popupapplet.cpp similarity index 100% rename from popupapplet.cpp rename to plasma/popupapplet.cpp diff --git a/popupapplet.h b/plasma/popupapplet.h similarity index 100% rename from popupapplet.h rename to plasma/popupapplet.h diff --git a/private/applet_p.h b/plasma/private/applet_p.h similarity index 100% rename from private/applet_p.h rename to plasma/private/applet_p.h diff --git a/private/applethandle.cpp b/plasma/private/applethandle.cpp similarity index 100% rename from private/applethandle.cpp rename to plasma/private/applethandle.cpp diff --git a/private/applethandle_p.h b/plasma/private/applethandle_p.h similarity index 100% rename from private/applethandle_p.h rename to plasma/private/applethandle_p.h diff --git a/private/containment_p.h b/plasma/private/containment_p.h similarity index 100% rename from private/containment_p.h rename to plasma/private/containment_p.h diff --git a/private/datacontainer_p.cpp b/plasma/private/datacontainer_p.cpp similarity index 100% rename from private/datacontainer_p.cpp rename to plasma/private/datacontainer_p.cpp diff --git a/private/datacontainer_p.h b/plasma/private/datacontainer_p.h similarity index 100% rename from private/datacontainer_p.h rename to plasma/private/datacontainer_p.h diff --git a/private/dataengine_p.h b/plasma/private/dataengine_p.h similarity index 100% rename from private/dataengine_p.h rename to plasma/private/dataengine_p.h diff --git a/private/desktoptoolbox.cpp b/plasma/private/desktoptoolbox.cpp similarity index 100% rename from private/desktoptoolbox.cpp rename to plasma/private/desktoptoolbox.cpp diff --git a/private/desktoptoolbox_p.h b/plasma/private/desktoptoolbox_p.h similarity index 100% rename from private/desktoptoolbox_p.h rename to plasma/private/desktoptoolbox_p.h diff --git a/private/extender_p.h b/plasma/private/extender_p.h similarity index 100% rename from private/extender_p.h rename to plasma/private/extender_p.h diff --git a/private/extenderapplet.cpp b/plasma/private/extenderapplet.cpp similarity index 100% rename from private/extenderapplet.cpp rename to plasma/private/extenderapplet.cpp diff --git a/private/extenderapplet_p.h b/plasma/private/extenderapplet_p.h similarity index 100% rename from private/extenderapplet_p.h rename to plasma/private/extenderapplet_p.h diff --git a/private/extenderitem_p.h b/plasma/private/extenderitem_p.h similarity index 100% rename from private/extenderitem_p.h rename to plasma/private/extenderitem_p.h diff --git a/private/nativetabbar.cpp b/plasma/private/nativetabbar.cpp similarity index 100% rename from private/nativetabbar.cpp rename to plasma/private/nativetabbar.cpp diff --git a/private/nativetabbar_p.h b/plasma/private/nativetabbar_p.h similarity index 100% rename from private/nativetabbar_p.h rename to plasma/private/nativetabbar_p.h diff --git a/private/packages.cpp b/plasma/private/packages.cpp similarity index 100% rename from private/packages.cpp rename to plasma/private/packages.cpp diff --git a/private/packages_p.h b/plasma/private/packages_p.h similarity index 100% rename from private/packages_p.h rename to plasma/private/packages_p.h diff --git a/private/paneltoolbox.cpp b/plasma/private/paneltoolbox.cpp similarity index 100% rename from private/paneltoolbox.cpp rename to plasma/private/paneltoolbox.cpp diff --git a/private/paneltoolbox_p.h b/plasma/private/paneltoolbox_p.h similarity index 100% rename from private/paneltoolbox_p.h rename to plasma/private/paneltoolbox_p.h diff --git a/private/popupapplet_p.h b/plasma/private/popupapplet_p.h similarity index 100% rename from private/popupapplet_p.h rename to plasma/private/popupapplet_p.h diff --git a/private/service_p.h b/plasma/private/service_p.h similarity index 100% rename from private/service_p.h rename to plasma/private/service_p.h diff --git a/private/sharedtimer_p.h b/plasma/private/sharedtimer_p.h similarity index 100% rename from private/sharedtimer_p.h rename to plasma/private/sharedtimer_p.h diff --git a/private/style.cpp b/plasma/private/style.cpp similarity index 100% rename from private/style.cpp rename to plasma/private/style.cpp diff --git a/private/style.h b/plasma/private/style.h similarity index 100% rename from private/style.h rename to plasma/private/style.h diff --git a/private/toolbox.cpp b/plasma/private/toolbox.cpp similarity index 100% rename from private/toolbox.cpp rename to plasma/private/toolbox.cpp diff --git a/private/toolbox_p.h b/plasma/private/toolbox_p.h similarity index 100% rename from private/toolbox_p.h rename to plasma/private/toolbox_p.h diff --git a/private/tooltip.cpp b/plasma/private/tooltip.cpp similarity index 100% rename from private/tooltip.cpp rename to plasma/private/tooltip.cpp diff --git a/private/tooltip_p.h b/plasma/private/tooltip_p.h similarity index 100% rename from private/tooltip_p.h rename to plasma/private/tooltip_p.h diff --git a/private/windowpreview.cpp b/plasma/private/windowpreview.cpp similarity index 100% rename from private/windowpreview.cpp rename to plasma/private/windowpreview.cpp diff --git a/private/windowpreview_p.h b/plasma/private/windowpreview_p.h similarity index 100% rename from private/windowpreview_p.h rename to plasma/private/windowpreview_p.h diff --git a/querymatch.cpp b/plasma/querymatch.cpp similarity index 100% rename from querymatch.cpp rename to plasma/querymatch.cpp diff --git a/querymatch.h b/plasma/querymatch.h similarity index 100% rename from querymatch.h rename to plasma/querymatch.h diff --git a/runnercontext.cpp b/plasma/runnercontext.cpp similarity index 100% rename from runnercontext.cpp rename to plasma/runnercontext.cpp diff --git a/runnercontext.h b/plasma/runnercontext.h similarity index 100% rename from runnercontext.h rename to plasma/runnercontext.h diff --git a/runnermanager.cpp b/plasma/runnermanager.cpp similarity index 100% rename from runnermanager.cpp rename to plasma/runnermanager.cpp diff --git a/runnermanager.h b/plasma/runnermanager.h similarity index 100% rename from runnermanager.h rename to plasma/runnermanager.h diff --git a/scripting/appletscript.cpp b/plasma/scripting/appletscript.cpp similarity index 100% rename from scripting/appletscript.cpp rename to plasma/scripting/appletscript.cpp diff --git a/scripting/appletscript.h b/plasma/scripting/appletscript.h similarity index 100% rename from scripting/appletscript.h rename to plasma/scripting/appletscript.h diff --git a/scripting/dataenginescript.cpp b/plasma/scripting/dataenginescript.cpp similarity index 100% rename from scripting/dataenginescript.cpp rename to plasma/scripting/dataenginescript.cpp diff --git a/scripting/dataenginescript.h b/plasma/scripting/dataenginescript.h similarity index 100% rename from scripting/dataenginescript.h rename to plasma/scripting/dataenginescript.h diff --git a/scripting/plasmoids.knsrc b/plasma/scripting/plasmoids.knsrc similarity index 100% rename from scripting/plasmoids.knsrc rename to plasma/scripting/plasmoids.knsrc diff --git a/scripting/runnerscript.cpp b/plasma/scripting/runnerscript.cpp similarity index 100% rename from scripting/runnerscript.cpp rename to plasma/scripting/runnerscript.cpp diff --git a/scripting/runnerscript.h b/plasma/scripting/runnerscript.h similarity index 100% rename from scripting/runnerscript.h rename to plasma/scripting/runnerscript.h diff --git a/scripting/scriptengine.cpp b/plasma/scripting/scriptengine.cpp similarity index 100% rename from scripting/scriptengine.cpp rename to plasma/scripting/scriptengine.cpp diff --git a/scripting/scriptengine.h b/plasma/scripting/scriptengine.h similarity index 100% rename from scripting/scriptengine.h rename to plasma/scripting/scriptengine.h diff --git a/scripting/uiloader.cpp b/plasma/scripting/uiloader.cpp similarity index 100% rename from scripting/uiloader.cpp rename to plasma/scripting/uiloader.cpp diff --git a/scripting/uiloader.h b/plasma/scripting/uiloader.h similarity index 100% rename from scripting/uiloader.h rename to plasma/scripting/uiloader.h diff --git a/service.cpp b/plasma/service.cpp similarity index 100% rename from service.cpp rename to plasma/service.cpp diff --git a/service.h b/plasma/service.h similarity index 100% rename from service.h rename to plasma/service.h diff --git a/servicejob.cpp b/plasma/servicejob.cpp similarity index 100% rename from servicejob.cpp rename to plasma/servicejob.cpp diff --git a/servicejob.h b/plasma/servicejob.h similarity index 100% rename from servicejob.h rename to plasma/servicejob.h diff --git a/servicetypes/plasma-animator.desktop b/plasma/servicetypes/plasma-animator.desktop similarity index 100% rename from servicetypes/plasma-animator.desktop rename to plasma/servicetypes/plasma-animator.desktop diff --git a/servicetypes/plasma-applet-extenderapplet.desktop b/plasma/servicetypes/plasma-applet-extenderapplet.desktop similarity index 100% rename from servicetypes/plasma-applet-extenderapplet.desktop rename to plasma/servicetypes/plasma-applet-extenderapplet.desktop diff --git a/servicetypes/plasma-applet.desktop b/plasma/servicetypes/plasma-applet.desktop similarity index 100% rename from servicetypes/plasma-applet.desktop rename to plasma/servicetypes/plasma-applet.desktop diff --git a/servicetypes/plasma-containment.desktop b/plasma/servicetypes/plasma-containment.desktop similarity index 100% rename from servicetypes/plasma-containment.desktop rename to plasma/servicetypes/plasma-containment.desktop diff --git a/servicetypes/plasma-dataengine.desktop b/plasma/servicetypes/plasma-dataengine.desktop similarity index 100% rename from servicetypes/plasma-dataengine.desktop rename to plasma/servicetypes/plasma-dataengine.desktop diff --git a/servicetypes/plasma-packagestructure.desktop b/plasma/servicetypes/plasma-packagestructure.desktop similarity index 100% rename from servicetypes/plasma-packagestructure.desktop rename to plasma/servicetypes/plasma-packagestructure.desktop diff --git a/servicetypes/plasma-runner.desktop b/plasma/servicetypes/plasma-runner.desktop similarity index 100% rename from servicetypes/plasma-runner.desktop rename to plasma/servicetypes/plasma-runner.desktop diff --git a/servicetypes/plasma-scriptengine.desktop b/plasma/servicetypes/plasma-scriptengine.desktop similarity index 100% rename from servicetypes/plasma-scriptengine.desktop rename to plasma/servicetypes/plasma-scriptengine.desktop diff --git a/servicetypes/plasma-wallpaper.desktop b/plasma/servicetypes/plasma-wallpaper.desktop similarity index 100% rename from servicetypes/plasma-wallpaper.desktop rename to plasma/servicetypes/plasma-wallpaper.desktop diff --git a/svg.cpp b/plasma/svg.cpp similarity index 100% rename from svg.cpp rename to plasma/svg.cpp diff --git a/svg.h b/plasma/svg.h similarity index 100% rename from svg.h rename to plasma/svg.h diff --git a/tests/CMakeLists.txt b/plasma/tests/CMakeLists.txt similarity index 100% rename from tests/CMakeLists.txt rename to plasma/tests/CMakeLists.txt diff --git a/tests/TODO b/plasma/tests/TODO similarity index 100% rename from tests/TODO rename to plasma/tests/TODO diff --git a/tests/packagemetadatatest.cpp b/plasma/tests/packagemetadatatest.cpp similarity index 100% rename from tests/packagemetadatatest.cpp rename to plasma/tests/packagemetadatatest.cpp diff --git a/tests/packagemetadatatest.desktop b/plasma/tests/packagemetadatatest.desktop similarity index 100% rename from tests/packagemetadatatest.desktop rename to plasma/tests/packagemetadatatest.desktop diff --git a/tests/packagemetadatatest.h b/plasma/tests/packagemetadatatest.h similarity index 100% rename from tests/packagemetadatatest.h rename to plasma/tests/packagemetadatatest.h diff --git a/tests/packagestructuretest.cpp b/plasma/tests/packagestructuretest.cpp similarity index 100% rename from tests/packagestructuretest.cpp rename to plasma/tests/packagestructuretest.cpp diff --git a/tests/packagestructuretest.h b/plasma/tests/packagestructuretest.h similarity index 100% rename from tests/packagestructuretest.h rename to plasma/tests/packagestructuretest.h diff --git a/tests/plasmoidpackagerc b/plasma/tests/plasmoidpackagerc similarity index 100% rename from tests/plasmoidpackagerc rename to plasma/tests/plasmoidpackagerc diff --git a/tests/plasmoidpackagetest.cpp b/plasma/tests/plasmoidpackagetest.cpp similarity index 100% rename from tests/plasmoidpackagetest.cpp rename to plasma/tests/plasmoidpackagetest.cpp diff --git a/tests/plasmoidpackagetest.h b/plasma/tests/plasmoidpackagetest.h similarity index 100% rename from tests/plasmoidpackagetest.h rename to plasma/tests/plasmoidpackagetest.h diff --git a/tests/sharedtimertest.h b/plasma/tests/sharedtimertest.h similarity index 100% rename from tests/sharedtimertest.h rename to plasma/tests/sharedtimertest.h diff --git a/tests/testengine/CMakeLists.txt b/plasma/tests/testengine/CMakeLists.txt similarity index 100% rename from tests/testengine/CMakeLists.txt rename to plasma/tests/testengine/CMakeLists.txt diff --git a/tests/testengine/plasma-dataengine-testengine.desktop b/plasma/tests/testengine/plasma-dataengine-testengine.desktop similarity index 100% rename from tests/testengine/plasma-dataengine-testengine.desktop rename to plasma/tests/testengine/plasma-dataengine-testengine.desktop diff --git a/tests/testengine/testengine.cpp b/plasma/tests/testengine/testengine.cpp similarity index 100% rename from tests/testengine/testengine.cpp rename to plasma/tests/testengine/testengine.cpp diff --git a/tests/testengine/testengine.h b/plasma/tests/testengine/testengine.h similarity index 100% rename from tests/testengine/testengine.h rename to plasma/tests/testengine/testengine.h diff --git a/theme.cpp b/plasma/theme.cpp similarity index 100% rename from theme.cpp rename to plasma/theme.cpp diff --git a/theme.h b/plasma/theme.h similarity index 100% rename from theme.h rename to plasma/theme.h diff --git a/tooltipcontent.cpp b/plasma/tooltipcontent.cpp similarity index 100% rename from tooltipcontent.cpp rename to plasma/tooltipcontent.cpp diff --git a/tooltipcontent.h b/plasma/tooltipcontent.h similarity index 100% rename from tooltipcontent.h rename to plasma/tooltipcontent.h diff --git a/tooltipmanager.cpp b/plasma/tooltipmanager.cpp similarity index 100% rename from tooltipmanager.cpp rename to plasma/tooltipmanager.cpp diff --git a/tooltipmanager.h b/plasma/tooltipmanager.h similarity index 100% rename from tooltipmanager.h rename to plasma/tooltipmanager.h diff --git a/version.cpp b/plasma/version.cpp similarity index 100% rename from version.cpp rename to plasma/version.cpp diff --git a/version.h b/plasma/version.h similarity index 100% rename from version.h rename to plasma/version.h diff --git a/view.cpp b/plasma/view.cpp similarity index 100% rename from view.cpp rename to plasma/view.cpp diff --git a/view.h b/plasma/view.h similarity index 100% rename from view.h rename to plasma/view.h diff --git a/wallpaper.cpp b/plasma/wallpaper.cpp similarity index 100% rename from wallpaper.cpp rename to plasma/wallpaper.cpp diff --git a/wallpaper.h b/plasma/wallpaper.h similarity index 100% rename from wallpaper.h rename to plasma/wallpaper.h diff --git a/widgets/busywidget.cpp b/plasma/widgets/busywidget.cpp similarity index 100% rename from widgets/busywidget.cpp rename to plasma/widgets/busywidget.cpp diff --git a/widgets/busywidget.h b/plasma/widgets/busywidget.h similarity index 100% rename from widgets/busywidget.h rename to plasma/widgets/busywidget.h diff --git a/widgets/checkbox.cpp b/plasma/widgets/checkbox.cpp similarity index 100% rename from widgets/checkbox.cpp rename to plasma/widgets/checkbox.cpp diff --git a/widgets/checkbox.h b/plasma/widgets/checkbox.h similarity index 100% rename from widgets/checkbox.h rename to plasma/widgets/checkbox.h diff --git a/widgets/combobox.cpp b/plasma/widgets/combobox.cpp similarity index 100% rename from widgets/combobox.cpp rename to plasma/widgets/combobox.cpp diff --git a/widgets/combobox.h b/plasma/widgets/combobox.h similarity index 100% rename from widgets/combobox.h rename to plasma/widgets/combobox.h diff --git a/widgets/flashinglabel.cpp b/plasma/widgets/flashinglabel.cpp similarity index 100% rename from widgets/flashinglabel.cpp rename to plasma/widgets/flashinglabel.cpp diff --git a/widgets/flashinglabel.h b/plasma/widgets/flashinglabel.h similarity index 100% rename from widgets/flashinglabel.h rename to plasma/widgets/flashinglabel.h diff --git a/widgets/frame.cpp b/plasma/widgets/frame.cpp similarity index 100% rename from widgets/frame.cpp rename to plasma/widgets/frame.cpp diff --git a/widgets/frame.h b/plasma/widgets/frame.h similarity index 100% rename from widgets/frame.h rename to plasma/widgets/frame.h diff --git a/widgets/groupbox.cpp b/plasma/widgets/groupbox.cpp similarity index 100% rename from widgets/groupbox.cpp rename to plasma/widgets/groupbox.cpp diff --git a/widgets/groupbox.h b/plasma/widgets/groupbox.h similarity index 100% rename from widgets/groupbox.h rename to plasma/widgets/groupbox.h diff --git a/widgets/iconwidget.cpp b/plasma/widgets/iconwidget.cpp similarity index 100% rename from widgets/iconwidget.cpp rename to plasma/widgets/iconwidget.cpp diff --git a/widgets/iconwidget.h b/plasma/widgets/iconwidget.h similarity index 100% rename from widgets/iconwidget.h rename to plasma/widgets/iconwidget.h diff --git a/widgets/iconwidget_p.h b/plasma/widgets/iconwidget_p.h similarity index 100% rename from widgets/iconwidget_p.h rename to plasma/widgets/iconwidget_p.h diff --git a/widgets/label.cpp b/plasma/widgets/label.cpp similarity index 100% rename from widgets/label.cpp rename to plasma/widgets/label.cpp diff --git a/widgets/label.h b/plasma/widgets/label.h similarity index 100% rename from widgets/label.h rename to plasma/widgets/label.h diff --git a/widgets/lineedit.cpp b/plasma/widgets/lineedit.cpp similarity index 100% rename from widgets/lineedit.cpp rename to plasma/widgets/lineedit.cpp diff --git a/widgets/lineedit.h b/plasma/widgets/lineedit.h similarity index 100% rename from widgets/lineedit.h rename to plasma/widgets/lineedit.h diff --git a/widgets/make_widget.sh b/plasma/widgets/make_widget.sh similarity index 100% rename from widgets/make_widget.sh rename to plasma/widgets/make_widget.sh diff --git a/widgets/meter.cpp b/plasma/widgets/meter.cpp similarity index 100% rename from widgets/meter.cpp rename to plasma/widgets/meter.cpp diff --git a/widgets/meter.h b/plasma/widgets/meter.h similarity index 100% rename from widgets/meter.h rename to plasma/widgets/meter.h diff --git a/widgets/pushbutton.cpp b/plasma/widgets/pushbutton.cpp similarity index 100% rename from widgets/pushbutton.cpp rename to plasma/widgets/pushbutton.cpp diff --git a/widgets/pushbutton.h b/plasma/widgets/pushbutton.h similarity index 100% rename from widgets/pushbutton.h rename to plasma/widgets/pushbutton.h diff --git a/widgets/radiobutton.cpp b/plasma/widgets/radiobutton.cpp similarity index 100% rename from widgets/radiobutton.cpp rename to plasma/widgets/radiobutton.cpp diff --git a/widgets/radiobutton.h b/plasma/widgets/radiobutton.h similarity index 100% rename from widgets/radiobutton.h rename to plasma/widgets/radiobutton.h diff --git a/widgets/scrollbar.cpp b/plasma/widgets/scrollbar.cpp similarity index 100% rename from widgets/scrollbar.cpp rename to plasma/widgets/scrollbar.cpp diff --git a/widgets/scrollbar.h b/plasma/widgets/scrollbar.h similarity index 100% rename from widgets/scrollbar.h rename to plasma/widgets/scrollbar.h diff --git a/widgets/signalplotter.cpp b/plasma/widgets/signalplotter.cpp similarity index 100% rename from widgets/signalplotter.cpp rename to plasma/widgets/signalplotter.cpp diff --git a/widgets/signalplotter.h b/plasma/widgets/signalplotter.h similarity index 100% rename from widgets/signalplotter.h rename to plasma/widgets/signalplotter.h diff --git a/widgets/slider.cpp b/plasma/widgets/slider.cpp similarity index 100% rename from widgets/slider.cpp rename to plasma/widgets/slider.cpp diff --git a/widgets/slider.h b/plasma/widgets/slider.h similarity index 100% rename from widgets/slider.h rename to plasma/widgets/slider.h diff --git a/widgets/svgwidget.cpp b/plasma/widgets/svgwidget.cpp similarity index 100% rename from widgets/svgwidget.cpp rename to plasma/widgets/svgwidget.cpp diff --git a/widgets/svgwidget.h b/plasma/widgets/svgwidget.h similarity index 100% rename from widgets/svgwidget.h rename to plasma/widgets/svgwidget.h diff --git a/widgets/tabbar.cpp b/plasma/widgets/tabbar.cpp similarity index 100% rename from widgets/tabbar.cpp rename to plasma/widgets/tabbar.cpp diff --git a/widgets/tabbar.h b/plasma/widgets/tabbar.h similarity index 100% rename from widgets/tabbar.h rename to plasma/widgets/tabbar.h diff --git a/widgets/template.cpp b/plasma/widgets/template.cpp similarity index 100% rename from widgets/template.cpp rename to plasma/widgets/template.cpp diff --git a/widgets/template.h b/plasma/widgets/template.h similarity index 100% rename from widgets/template.h rename to plasma/widgets/template.h diff --git a/widgets/textedit.cpp b/plasma/widgets/textedit.cpp similarity index 100% rename from widgets/textedit.cpp rename to plasma/widgets/textedit.cpp diff --git a/widgets/textedit.h b/plasma/widgets/textedit.h similarity index 100% rename from widgets/textedit.h rename to plasma/widgets/textedit.h diff --git a/widgets/treeview.cpp b/plasma/widgets/treeview.cpp similarity index 100% rename from widgets/treeview.cpp rename to plasma/widgets/treeview.cpp diff --git a/widgets/treeview.h b/plasma/widgets/treeview.h similarity index 100% rename from widgets/treeview.h rename to plasma/widgets/treeview.h diff --git a/widgets/webview.cpp b/plasma/widgets/webview.cpp similarity index 100% rename from widgets/webview.cpp rename to plasma/widgets/webview.cpp diff --git a/widgets/webview.h b/plasma/widgets/webview.h similarity index 100% rename from widgets/webview.h rename to plasma/widgets/webview.h diff --git a/private/qtjolie-branch/CMakeLists.txt b/private/qtjolie-branch/CMakeLists.txt deleted file mode 100644 index b00247053..000000000 --- a/private/qtjolie-branch/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -find_package(KDE4 REQUIRED) -include(KDE4Defaults) -include(MacroLibrary) - -add_definitions(${QT_DEFINITIONS} ${KDE4_DEFINITIONS}) -include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ${KDE4_INCLUDES}) - -add_subdirectory(sodep) -add_subdirectory(tests) diff --git a/private/qtjolie-branch/Mainpage.dox b/private/qtjolie-branch/Mainpage.dox deleted file mode 100644 index 0ec21a486..000000000 --- a/private/qtjolie-branch/Mainpage.dox +++ /dev/null @@ -1,4 +0,0 @@ -/** @mainpage SODEP - -*/ -// DOXYGEN_SET_PROJECT_NAME = Sodep diff --git a/private/qtjolie-branch/sodep/CMakeLists.txt b/private/qtjolie-branch/sodep/CMakeLists.txt deleted file mode 100644 index 70daacb2d..000000000 --- a/private/qtjolie-branch/sodep/CMakeLists.txt +++ /dev/null @@ -1,22 +0,0 @@ -project(sodep) - -include_directories(${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_CURRENT_BINARY_DIR} - ${QT_INCLUDE_DIR}) - -set(sodep_LIB_SRCS sodepvalue.cpp sodepfault.cpp sodepmessage.cpp) - -kde4_add_library(sodep SHARED ${sodep_LIB_SRCS}) - -target_link_libraries(sodep ${QT_QTCORE_LIBRARY}) - -install(TARGETS sodep - DESTINATION ${LIB_INSTALL_DIR}) - -set_target_properties(sodep PROPERTIES VERSION 1.0.0 SOVERSION 1) - -install(FILES - sodepvalue.h - sodepfault.h - sodepmessage.h - DESTINATION ${INCLUDE_INSTALL_DIR}) diff --git a/private/qtjolie-branch/sodep/sodepfault.cpp b/private/qtjolie-branch/sodep/sodepfault.cpp deleted file mode 100644 index 493c839d8..000000000 --- a/private/qtjolie-branch/sodep/sodepfault.cpp +++ /dev/null @@ -1,108 +0,0 @@ -/** - * This file is part of the KDE project - * Copyright (C) 2008 Kevin Ottens - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This 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 "sodepfault.h" - -#include - -#include "sodephelpers_p.h" - -class SodepFaultPrivate -{ -public: - QString name; - SodepValue data; -}; - -SodepFault::SodepFault() - : d(new SodepFaultPrivate) -{ - -} - -SodepFault::SodepFault(const QString &name, const SodepValue &data) - : d(new SodepFaultPrivate) -{ - d->name = name; - d->data = data; -} - -SodepFault::SodepFault(const SodepFault &other) - : d(new SodepFaultPrivate) -{ - *d = *other.d; -} - -SodepFault::~SodepFault() -{ - delete d; -} - -SodepFault &SodepFault::operator=(const SodepFault &other) -{ - *d = *other.d; - - return *this; -} - -QString SodepFault::name() const -{ - return d->name; -} - -SodepValue SodepFault::data() const -{ - return d->data; -} - -bool SodepFault::isValid() const -{ - return !d->name.isEmpty(); -} - -void SodepFault::writeTo(QIODevice &io) const -{ - if (!isValid()) { - io.putChar(0); - return; - } - - io.putChar(1); - sodepWrite(io, name()); - d->data.writeTo(io); -} - -SodepFault SodepFault::readFrom(QIODevice &io) -{ - char code; - io.getChar(&code); - - if (code!=1) { - return SodepFault(); - } - - SodepFault result; - - result.d->name = sodepReadString(io); - result.d->data = SodepValue::readFrom(io); - - return result; -} - diff --git a/private/qtjolie-branch/sodep/sodepfault.h b/private/qtjolie-branch/sodep/sodepfault.h deleted file mode 100644 index 531e5aaee..000000000 --- a/private/qtjolie-branch/sodep/sodepfault.h +++ /dev/null @@ -1,52 +0,0 @@ -/** - * This file is part of the KDE project - * Copyright (C) 2008 Kevin Ottens - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This 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 SODEPFAULT_H -#define SODEPFAULT_H - -#include - -class SodepFaultPrivate; - -class Q_DECL_EXPORT SodepFault -{ -public: - SodepFault(); - explicit SodepFault(const QString &name, const SodepValue &data = SodepValue()); - - SodepFault(const SodepFault &other); - - ~SodepFault(); - - SodepFault &operator=(const SodepFault &other); - - QString name() const; - SodepValue data() const; - - bool isValid() const; - - void writeTo(QIODevice &io) const; - static SodepFault readFrom(QIODevice &io); - -private: - SodepFaultPrivate * const d; -}; - -#endif diff --git a/private/qtjolie-branch/sodep/sodephelpers_p.h b/private/qtjolie-branch/sodep/sodephelpers_p.h deleted file mode 100644 index 544e7fcd6..000000000 --- a/private/qtjolie-branch/sodep/sodephelpers_p.h +++ /dev/null @@ -1,95 +0,0 @@ -/** - * This file is part of the KDE project - * Copyright (C) 2008 Kevin Ottens - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This 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 SODEPHELPERS_P_H -#define SODEPHELPERS_P_H - -#include -#include - -inline void sodepWrite(QIODevice &io, double value) -{ - const char *in = (const char*)&value; - char out[8]; - - for (int i=0; i<8; ++i) { - out[i] = in[7-i]; - } - - io.write(out, 8); -} - -inline void sodepWrite(QIODevice &io, qint32 value) -{ - const char *in = (const char*)&value; - char out[4]; - - for (int i=0; i<4; ++i) { - out[i] = in[3-i]; - } - - io.write(out, 4); -} - -inline void sodepWrite(QIODevice &io, const QString &value) -{ - QByteArray data = value.toUtf8(); - sodepWrite(io, data.size()); - io.write(data); -} - -inline double sodepReadDouble(QIODevice &io) -{ - double d; - char *out = (char*)&d; - char in[8]; - - io.read(in, 8); - - for (int i=0; i<8; ++i) { - out[i] = in[7-i]; - } - - return d; -} - -inline qint32 sodepReadInt(QIODevice &io) -{ - qint32 i; - char *out = (char*)&i; - char in[4]; - - io.read(in, 4); - - for (int j=0; j<4; ++j) { - out[j] = in[3-j]; - } - return i; -} - -inline QString sodepReadString(QIODevice &io) -{ - qint32 length = sodepReadInt(io); - QByteArray data = io.read(length); - return QString::fromUtf8(data); -} - - -#endif diff --git a/private/qtjolie-branch/sodep/sodepmessage.cpp b/private/qtjolie-branch/sodep/sodepmessage.cpp deleted file mode 100644 index 8d058e3a0..000000000 --- a/private/qtjolie-branch/sodep/sodepmessage.cpp +++ /dev/null @@ -1,120 +0,0 @@ -/** - * This file is part of the KDE project - * Copyright (C) 2008 Kevin Ottens - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This 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 "sodepmessage.h" - -#include - -#include "sodephelpers_p.h" - -class SodepMessagePrivate -{ -public: - QString resourcePath; - QString operationName; - SodepFault fault; - SodepValue data; -}; - -SodepMessage::SodepMessage() - : d(new SodepMessagePrivate) -{ -} - -SodepMessage::SodepMessage(const QString &resourcePath, const QString &operationName) - : d(new SodepMessagePrivate) -{ - d->resourcePath = resourcePath; - d->operationName = operationName; -} - -SodepMessage::SodepMessage(const SodepMessage &other) - : d(new SodepMessagePrivate) -{ - *d = *other.d; -} - -SodepMessage::~SodepMessage() -{ - delete d; -} - -SodepMessage &SodepMessage::operator=(const SodepMessage &other) -{ - *d = *other.d; - - return *this; -} - -QString SodepMessage::resourcePath() const -{ - return d->resourcePath; -} - -QString SodepMessage::operationName() const -{ - return d->operationName; -} - -SodepFault SodepMessage::fault() const -{ - return d->fault; -} - -void SodepMessage::setFault(const SodepFault &fault) -{ - d->fault = fault; -} - -SodepValue SodepMessage::data() const -{ - return d->data; -} - -void SodepMessage::setData(const SodepValue &data) -{ - d->data = data; -} - -bool SodepMessage::isValid() -{ - return !d->resourcePath.isEmpty() && !d->operationName.isEmpty(); -} - -void SodepMessage::writeTo(QIODevice &io) const -{ - sodepWrite(io, d->resourcePath); - sodepWrite(io, d->operationName); - d->fault.writeTo(io); - d->data.writeTo(io); -} - -SodepMessage SodepMessage::readFrom(QIODevice &io) -{ - SodepMessage result; - - result.d->resourcePath = sodepReadString(io); - result.d->operationName = sodepReadString(io); - result.d->fault = SodepFault::readFrom(io); - result.d->data = SodepValue::readFrom(io); - - return result; -} - diff --git a/private/qtjolie-branch/sodep/sodepmessage.h b/private/qtjolie-branch/sodep/sodepmessage.h deleted file mode 100644 index 4d72d0a98..000000000 --- a/private/qtjolie-branch/sodep/sodepmessage.h +++ /dev/null @@ -1,58 +0,0 @@ -/** - * This file is part of the KDE project - * Copyright (C) 2008 Kevin Ottens - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This 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 SODEPMESSAGE_H -#define SODEPMESSAGE_H - -#include -#include - -class SodepMessagePrivate; - -class Q_DECL_EXPORT SodepMessage -{ -public: - SodepMessage(); - explicit SodepMessage(const QString &resourcePath, - const QString &operationName); - SodepMessage(const SodepMessage &other); - ~SodepMessage(); - - SodepMessage &operator=(const SodepMessage &other); - - QString resourcePath() const; - QString operationName() const; - - SodepFault fault() const; - void setFault(const SodepFault &fault); - - SodepValue data() const; - void setData(const SodepValue &data); - - bool isValid(); - - void writeTo(QIODevice &io) const; - static SodepMessage readFrom(QIODevice &io); - -private: - SodepMessagePrivate * const d; -}; - -#endif diff --git a/private/qtjolie-branch/sodep/sodepvalue.cpp b/private/qtjolie-branch/sodep/sodepvalue.cpp deleted file mode 100644 index b43bb1764..000000000 --- a/private/qtjolie-branch/sodep/sodepvalue.cpp +++ /dev/null @@ -1,206 +0,0 @@ -/** - * This file is part of the KDE project - * Copyright (C) 2008 Kevin Ottens - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This 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 "sodepvalue.h" - -#include -#include - -#include "sodephelpers_p.h" - -class SodepValuePrivate -{ -public: - QVariant content; - QMap > children; -}; - -SodepValue::SodepValue() - : d(new SodepValuePrivate) -{ -} - -SodepValue::SodepValue(const QString &content) - : d(new SodepValuePrivate) -{ - d->content = content; -} - -SodepValue::SodepValue(qint32 content) - : d(new SodepValuePrivate) -{ - d->content = content; -} - -SodepValue::SodepValue(double content) - : d(new SodepValuePrivate) -{ - d->content = content; -} - -SodepValue::SodepValue(const SodepValue &other) - : d(new SodepValuePrivate) -{ - *d = *other.d; -} - -SodepValue::~SodepValue() -{ - delete d; -} - -SodepValue &SodepValue::operator=(const SodepValue &other) -{ - *d = *other.d; - - return *this; -} - -QStringList SodepValue::childrenNames() const -{ - return d->children.keys(); -} - -QList & SodepValue::children(const QString &name) -{ - return d->children[name]; -} - -const QList & SodepValue::children(const QString &name) const -{ - return d->children[name]; -} - -QString SodepValue::toString() const -{ - if (isString()) { - return d->content.toString(); - } else { - return QString(); - } -} - -qint32 SodepValue::toInt() const -{ - if (isInt()) { - return d->content.toInt(); - } else { - return 0; - } -} - -double SodepValue::toDouble() const -{ - if (isDouble()) { - return d->content.toDouble(); - } else { - return 0.0; - } -} - -bool SodepValue::isString() const -{ - return d->content.type()==QVariant::String; -} - -bool SodepValue::isInt() const -{ - return d->content.type()==QVariant::Int; -} - -bool SodepValue::isDouble() const -{ - return d->content.type()==QVariant::Double; -} - -bool SodepValue::isValid() const -{ - return isString() || isInt() || isDouble(); -} - -void SodepValue::writeTo(QIODevice &io) const -{ - if (isDouble()) { - io.putChar(3); - sodepWrite(io, toDouble()); - } else if (isInt()) { - io.putChar(2); - sodepWrite(io, toInt()); - } else if (isString()) { - io.putChar(1); - sodepWrite(io, toString()); - } else { - io.putChar(0); - } - - sodepWrite(io, d->children.size()); - - foreach (const QString &name, d->children.keys()) { - sodepWrite(io, name); - - QList values = d->children[name]; - qint32 valueCount = values.size(); - sodepWrite(io, valueCount); - for (int j=0; j values; - qint32 valueCount = sodepReadInt(io); - for (int j=0; jchildren[name] = values; - } - - return result; -} diff --git a/private/qtjolie-branch/sodep/sodepvalue.h b/private/qtjolie-branch/sodep/sodepvalue.h deleted file mode 100644 index bb2d09f89..000000000 --- a/private/qtjolie-branch/sodep/sodepvalue.h +++ /dev/null @@ -1,65 +0,0 @@ -/** - * This file is part of the KDE project - * Copyright (C) 2008 Kevin Ottens - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This 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 SODEPVALUE_H -#define SODEPVALUE_H - -#include -#include - -class SodepValuePrivate; - -class Q_DECL_EXPORT SodepValue -{ -public: - SodepValue(); - - explicit SodepValue(const QString &content); - explicit SodepValue(qint32 content); - explicit SodepValue(double content); - - SodepValue(const SodepValue &other); - - ~SodepValue(); - - SodepValue &operator=(const SodepValue &other); - - QStringList childrenNames() const; - QList &children(const QString &name); - const QList &children(const QString &name) const; - - QString toString() const; - qint32 toInt() const; - double toDouble() const; - - bool isString() const; - bool isInt() const; - bool isDouble() const; - - bool isValid() const; - - void writeTo(QIODevice &io) const; - static SodepValue readFrom(QIODevice &io); - -private: - SodepValuePrivate * const d; -}; - -#endif diff --git a/private/qtjolie-branch/tests/CMakeLists.txt b/private/qtjolie-branch/tests/CMakeLists.txt deleted file mode 100644 index 457c04d40..000000000 --- a/private/qtjolie-branch/tests/CMakeLists.txt +++ /dev/null @@ -1,25 +0,0 @@ -include_directories(${KDE4_INCLUDES} ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/../sodep) - -MACRO(SODEP_UNIT_TESTS) - FOREACH(_testname ${ARGN}) - kde4_add_unit_test(${_testname} NOGUI ${_testname}.cpp) - target_link_libraries(${_testname} ${QT_QTCORE_LIBRARY} ${QT_QTTEST_LIBRARY} sodep) - ENDFOREACH(_testname) -ENDMACRO(SODEP_UNIT_TESTS) - -MACRO(SODEP_EXECUTABLE_TESTS) - FOREACH(_testname ${ARGN}) - kde4_add_executable(${_testname} NOGUI TEST ${_testname}.cpp) - target_link_libraries(${_testname} ${QT_QTCORE_LIBRARY} ${QT_QTGUI_LIBRARY} ${QT_QTNETWORK_LIBRARY} sodep) - ENDFOREACH(_testname) -ENDMACRO(SODEP_EXECUTABLE_TESTS) - -SODEP_UNIT_TESTS( - sodepvaluetest - sodepfaulttest - sodepmessagetest -) - -SODEP_EXECUTABLE_TESTS( - sodepprintertest -) diff --git a/private/qtjolie-branch/tests/sodepfaulttest.cpp b/private/qtjolie-branch/tests/sodepfaulttest.cpp deleted file mode 100644 index 3be25efff..000000000 --- a/private/qtjolie-branch/tests/sodepfaulttest.cpp +++ /dev/null @@ -1,100 +0,0 @@ -/** - * This file is part of the KDE project - * Copyright (C) 2008 Kevin Ottens - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This 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 -#include - -#include -#include "sodeptesthelpers.h" - -class SodepFaultTest : public QObject -{ - Q_OBJECT - -private slots: - void shouldHandleInvalids() - { - SodepFault f; - - QCOMPARE(f.name(), QString()); - QVERIFY(!f.data().isValid()); - - QVERIFY(!f.isValid()); - } - void shouldVerifyInitialState() - { - SodepFault f1("blup"), f2("blop", SodepValue(42)); - - QCOMPARE(f1.name(), QString("blup")); - QVERIFY(!f1.data().isValid()); - - QCOMPARE(f2.name(), QString("blop")); - QVERIFY(f2.data().isValid()); - QCOMPARE(f2.data().toInt(), 42); - - f1 = f2; - - QCOMPARE(f1.name(), QString("blop")); - QVERIFY(f1.data().isValid()); - QCOMPARE(f1.data().toInt(), 42); - } - - void shouldBeSerializable_data() - { - SodepValue v(42); - QByteArray vSerial = QByteArray::fromHex("020000002A00000000"); - - QTest::addColumn("original"); - QTest::addColumn("serialized"); - - QTest::newRow("empty fault") << SodepFault() - << QByteArray::fromHex("00"); - QTest::newRow("no value fault") << SodepFault("foo") - << QByteArray::fromHex("0100000003")+QByteArray("foo") - + QByteArray::fromHex("0000000000"); - QTest::newRow("value fault") << SodepFault("bar", v) - << QByteArray::fromHex("0100000003")+QByteArray("bar") - + vSerial; - } - - void shouldBeSerializable() - { - QBuffer buffer; - - QFETCH(SodepFault, original); - QFETCH(QByteArray, serialized); - SodepFault result; - - buffer.open(QIODevice::WriteOnly); - original.writeTo(buffer); - buffer.close(); - - buffer.open(QIODevice::ReadOnly); - result = SodepFault::readFrom(buffer); - buffer.close(); - - sodepCompare(result, original); - QCOMPARE(buffer.data(), serialized); - } -}; - -QTEST_MAIN(SodepFaultTest) - -#include "sodepfaulttest.moc" diff --git a/private/qtjolie-branch/tests/sodepmessagetest.cpp b/private/qtjolie-branch/tests/sodepmessagetest.cpp deleted file mode 100644 index 3042c22c3..000000000 --- a/private/qtjolie-branch/tests/sodepmessagetest.cpp +++ /dev/null @@ -1,98 +0,0 @@ -/** - * This file is part of the KDE project - * Copyright (C) 2008 Kevin Ottens - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This 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 -#include - -#include -#include "sodeptesthelpers.h" - -class SodepMessageTest : public QObject -{ - Q_OBJECT - -private slots: - void shouldVerifyInitialState() - { - SodepMessage m1("/foo", "bar"); - SodepMessage m2("/pata/pata", "pon"); - - QCOMPARE(m1.resourcePath(), QString("/foo")); - QCOMPARE(m1.operationName(), QString("bar")); - - QCOMPARE(m2.resourcePath(), QString("/pata/pata")); - QCOMPARE(m2.operationName(), QString("pon")); - - m1 = m2; - - QCOMPARE(m1.resourcePath(), QString("/pata/pata")); - QCOMPARE(m1.operationName(), QString("pon")); - } - - void shouldBeSerializable_data() - { - SodepValue v(42); - QByteArray vSerial = QByteArray::fromHex("020000002A00000000"); - SodepFault f("foo"); - QByteArray fSerial = QByteArray::fromHex("0100000003")+QByteArray("foo") - + QByteArray::fromHex("0000000000"); - - QTest::addColumn("original"); - QTest::addColumn("serialized"); - - QTest::newRow("no payload message") << SodepMessage("/pata", "pon") - << QByteArray::fromHex("00000005")+QByteArray("/pata") - + QByteArray::fromHex("00000003")+QByteArray("pon") - + QByteArray::fromHex("00") - + QByteArray::fromHex("0000000000"); - SodepMessage payload("/pata", "pon"); - payload.setFault(f); - payload.setData(v); - QTest::newRow("payload message") << payload - << QByteArray::fromHex("00000005")+QByteArray("/pata") - + QByteArray::fromHex("00000003")+QByteArray("pon") - + fSerial - + vSerial; - } - - void shouldBeSerializable() - { - QBuffer buffer; - - QFETCH(SodepMessage, original); - QFETCH(QByteArray, serialized); - SodepMessage result; - - buffer.open(QIODevice::WriteOnly); - original.writeTo(buffer); - buffer.close(); - - buffer.open(QIODevice::ReadOnly); - result = SodepMessage::readFrom(buffer); - buffer.close(); - - sodepCompare(result, original); - QCOMPARE(buffer.data(), serialized); - } -}; - -QTEST_MAIN(SodepMessageTest) - -#include "sodepmessagetest.moc" diff --git a/private/qtjolie-branch/tests/sodepprintertest.cpp b/private/qtjolie-branch/tests/sodepprintertest.cpp deleted file mode 100644 index df2351c6d..000000000 --- a/private/qtjolie-branch/tests/sodepprintertest.cpp +++ /dev/null @@ -1,84 +0,0 @@ -/** - * This file is part of the KDE project - * Copyright (C) 2008 Kevin Ottens - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This 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 -#include -#include -#include -#include -#include - -#include -#include - -class MainWindow : public QWidget -{ - Q_OBJECT -public: - MainWindow() - { - setLayout(new QHBoxLayout()); - m_lineEdit = new QLineEdit(this); - layout()->addWidget(m_lineEdit); - - QPushButton *button = new QPushButton(this); - button->setText("SEND"); - layout()->addWidget(button); - connect(button, SIGNAL(clicked()), - this, SLOT(sendMessage())); - - m_socket.connectToHost("localhost", 10000); - if (!m_socket.waitForConnected(10000)) { - qDebug("Failed to connect!"); - return; - } - qDebug("Connected!"); - } - -private slots: - void sendMessage() - { - SodepMessage message("/", "printInput"); - message.setData(SodepValue(m_lineEdit->text())); - message.writeTo(m_socket); - - qDebug("Message sent:"); - QBuffer buffer; - buffer.open(QIODevice::WriteOnly); - message.writeTo(buffer); - buffer.close(); - qDebug(buffer.data().toHex()); - } -private: - QLineEdit *m_lineEdit; - QTcpSocket m_socket; -}; - -int main(int argc, char **argv) -{ - QApplication app(argc, argv); - - MainWindow w; - w.show(); - - return app.exec(); -} - -#include "sodepprintertest.moc" diff --git a/private/qtjolie-branch/tests/sodeptesthelpers.h b/private/qtjolie-branch/tests/sodeptesthelpers.h deleted file mode 100644 index 040e2565a..000000000 --- a/private/qtjolie-branch/tests/sodeptesthelpers.h +++ /dev/null @@ -1,79 +0,0 @@ -/** - * This file is part of the KDE project - * Copyright (C) 2008 Kevin Ottens - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This 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 SODEPTESTHELPERS_H -#define SODEPTESTHELPERS_H - -#include - -#include -#include -#include - -Q_DECLARE_METATYPE(SodepValue); - -inline void sodepCompare(const SodepValue &v1, const SodepValue &v2) -{ - QCOMPARE(v1.isValid(), v2.isValid()); - - QCOMPARE(v1.isString(), v2.isString()); - QCOMPARE(v1.isInt(), v2.isInt()); - QCOMPARE(v1.isDouble(), v2.isDouble()); - - QCOMPARE(v1.toString(), v2.toString()); - QCOMPARE(v1.toInt(), v2.toInt()); - QCOMPARE(v1.toDouble(), v2.toDouble()); - - QStringList v1Names = v1.childrenNames(); - QStringList v2Names = v2.childrenNames(); - QCOMPARE(v1Names, v2Names); - - foreach (const QString &name, v1Names) { - QList v1Values = v1.children(name); - QList v2Values = v2.children(name); - - QCOMPARE(v1Values.size(), v2Values.size()); - - for (int i=0; i - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This 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 -#include - -#include - -#include "sodeptesthelpers.h" - -class SodepValueTest : public QObject -{ - Q_OBJECT - -private slots: - void shouldHandleInvalids() - { - SodepValue v; - - QCOMPARE(v.toInt(), 0); - QCOMPARE(v.toDouble(), 0.0); - QCOMPARE(v.toString(), QString()); - - QVERIFY(!v.isValid()); - - QVERIFY(!v.isString()); - QVERIFY(!v.isInt()); - QVERIFY(!v.isDouble()); - } - - void shouldRespectIntValues() - { - SodepValue v1(42), v2; - - QCOMPARE(v1.toInt(), 42); - QCOMPARE(v2.toInt(), 0); - - QVERIFY(v1.isInt()); - QVERIFY(!v2.isInt()); - - v2 = v1; - - QCOMPARE(v2.toInt(), 42); - QVERIFY(v2.isInt()); - - QCOMPARE(v2.toDouble(), 0.0); - QCOMPARE(v2.toString(), QString()); - } - - void shouldRespectDoubleValues() - { - SodepValue v1(0.42), v2; - - QCOMPARE(v1.toDouble(), 0.42); - QCOMPARE(v2.toDouble(), 0.0); - - QVERIFY(v1.isDouble()); - QVERIFY(!v2.isDouble()); - - v2 = v1; - - QCOMPARE(v2.toDouble(), 0.42); - QVERIFY(v2.isDouble()); - - QCOMPARE(v2.toInt(), 0); - QCOMPARE(v2.toString(), QString()); - } - - void shouldRespectStringValues() - { - SodepValue v1("42"), v2; - - QCOMPARE(v1.toString(), QString("42")); - QCOMPARE(v2.toString(), QString()); - - QVERIFY(v1.isString()); - QVERIFY(!v2.isString()); - - v2 = v1; - - QCOMPARE(v2.toString(), QString("42")); - QVERIFY(v2.isString()); - - QCOMPARE(v2.toInt(), 0); - QCOMPARE(v2.toDouble(), 0.0); - } - - void shouldHandleChildren() - { - SodepValue v; - - v.children("first") << SodepValue(7) << SodepValue(8); - v.children("second") << SodepValue(42); - - QCOMPARE(v.children("second").size(), 1); - QCOMPARE(v.children("second")[0].toInt(), 42); - - QCOMPARE(v.children("first").size(), 2); - QCOMPARE(v.children("first")[0].toInt(), 7); - QCOMPARE(v.children("first")[1].toInt(), 8); - - QCOMPARE(v.children("bwaaaaah!").size(), 0); - } - - void shouldBeSerializable_data() - { - QTest::addColumn("original"); - QTest::addColumn("serialized"); - - QTest::newRow("empty value") << SodepValue() - << QByteArray::fromHex("0000000000"); - QTest::newRow("double value") << SodepValue(0.42) - << QByteArray::fromHex("033FDAE147AE147AE100000000"); - QTest::newRow("int value") << SodepValue(42) - << QByteArray::fromHex("020000002A00000000"); - QTest::newRow("string value") << SodepValue("foo") - << QByteArray::fromHex("0100000003")+QByteArray("foo") - + QByteArray::fromHex("00000000"); - - SodepValue complex("complex"); - complex.children("foo") << SodepValue(42); - complex.children("bar") << SodepValue(0.42); - QTest::newRow("complex value") << complex - << QByteArray::fromHex("0100000007")+QByteArray("complex") - + QByteArray::fromHex("00000002") // two children - + QByteArray::fromHex("00000003")+QByteArray("bar") - + QByteArray::fromHex("00000001") // one value - + QByteArray::fromHex("033FDAE147AE147AE100000000") - + QByteArray::fromHex("00000003")+QByteArray("foo") - + QByteArray::fromHex("00000001") // one value - + QByteArray::fromHex("020000002A00000000"); - } - - void shouldBeSerializable() - { - QBuffer buffer; - - QFETCH(SodepValue, original); - QFETCH(QByteArray, serialized); - SodepValue result; - - buffer.open(QIODevice::WriteOnly); - original.writeTo(buffer); - buffer.close(); - - buffer.open(QIODevice::ReadOnly); - result = SodepValue::readFrom(buffer); - buffer.close(); - - sodepCompare(result, original); - QCOMPARE(buffer.data(), serialized); - } -}; - -QTEST_MAIN(SodepValueTest) - -#include "sodepvaluetest.moc" diff --git a/solid/CMakeLists.txt b/solid/CMakeLists.txt new file mode 100644 index 000000000..d2f04fb3b --- /dev/null +++ b/solid/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory( control ) + diff --git a/solid/Mainpage.dox b/solid/Mainpage.dox new file mode 100644 index 000000000..81f714c12 --- /dev/null +++ b/solid/Mainpage.dox @@ -0,0 +1,8 @@ +/** @mainpage SolidControl library + +*/ + +// DOXYGEN_SET_PROJECT_NAME = libsolidcontrol +// DOXYGEN_SET_RECURSIVE = YES +// vim:ts=4:sw=4:expandtab:filetype=doxygen + diff --git a/solid/control/CMakeLists.txt b/solid/control/CMakeLists.txt new file mode 100644 index 000000000..5c6d18966 --- /dev/null +++ b/solid/control/CMakeLists.txt @@ -0,0 +1,50 @@ +include_directories( ${CMAKE_SOURCE_DIR}/workspace/libs ) + +add_subdirectory( ifaces ) +add_subdirectory( backends ) +add_subdirectory( tests ) + +########### next target ############### + +set(solidcontrol_LIB_SRCS + frontendobject.cpp + managerbase.cpp + powermanager.cpp + networking.cpp + networkmanager.cpp + networkinterface.cpp + networkcdmainterface.cpp + networkgsminterface.cpp + networkserialinterface.cpp + networkipv4config.cpp + wirednetworkinterface.cpp + wirelessaccesspoint.cpp + wirelessnetworkinterface.cpp + bluetoothinterface.cpp + bluetoothmanager.cpp + bluetoothremotedevice.cpp + bluetoothinputdevice.cpp + bluetoothsecurity.cpp +) + +qt4_add_dbus_interface(solidcontrol_LIB_SRCS org.kde.Solid.Networking.xml org_kde_solid_networking) + +kde4_add_library(solidcontrol SHARED ${solidcontrol_LIB_SRCS}) + +target_link_libraries(solidcontrol ${KDE4_KDECORE_LIBS} ${KDE4_SOLID_LIBS} ${QT_QTNETWORK_LIBRARY} solidcontrolifaces ) + +set_target_properties(solidcontrol PROPERTIES VERSION ${GENERIC_LIB_VERSION} SOVERSION ${GENERIC_LIB_SOVERSION} ) +install(TARGETS solidcontrol ${INSTALL_TARGETS_DEFAULT_ARGS} ) + + +########### install files ############### + +install( FILES solidpowermanager.desktop solidnetworkmanager.desktop solidbluetoothmanager.desktop DESTINATION ${SERVICETYPES_INSTALL_DIR} ) +install( FILES powermanager.h networkmanager.h networkinterface.h wirednetworkinterface.h + wirelessnetworkinterface.h wirelessaccesspoint.h bluetoothmanager.h bluetoothinterface.h + bluetoothremotedevice.h bluetoothinputdevice.h bluetoothsecurity.h + singletondefs.h networking.h networkipv4config.h solid_control_export.h + networkcdmainterface.h networkgsminterface.h networkserialinterface.h + DESTINATION +${INCLUDE_INSTALL_DIR}/solid/control COMPONENT Devel) + diff --git a/solid/control/Messages.sh b/solid/control/Messages.sh new file mode 100755 index 000000000..b9a8080b9 --- /dev/null +++ b/solid/control/Messages.sh @@ -0,0 +1,2 @@ +#! /usr/bin/env bash +$XGETTEXT *.cpp -o $podir/solidcontrol.pot diff --git a/solid/control/authentication.cpp b/solid/control/authentication.cpp new file mode 100644 index 000000000..c1c0d517a --- /dev/null +++ b/solid/control/authentication.cpp @@ -0,0 +1,336 @@ +/* This file is part of the KDE project + Copyright (C) 2006 Kevin Ottens + Copyright (C) 2006,2007 Will Stephenson + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#include "soliddefs_p.h" +#include "authentication.h" +#include "networkmanager_p.h" +#include +#include +#include + +namespace Solid +{ +namespace Control +{ + class AuthenticationValidator::Private + { + public: + QObject *backendObject; + }; + + class Authentication::Private + { + public: + SecretMap secrets; + }; + + class AuthenticationWep::Private + { + public: + WepMethod method; + WepType type; + int keyLength; + }; + + class AuthenticationWpa::Private + { + public: + WpaProtocol protocol; + WpaVersion version; + WpaKeyManagement mgmt; + }; + + class AuthenticationWpaEnterprise::Private + { + public: + QString identity; + QString anonIdentity; + QString certClient; + QString certCA; + QString certPrivate; + EapMethod method; + QString idPasswordKey; + QString certPrivatePasswordKey; + }; +} +} + + +/******************************************************************************/ + +Solid::Control::Authentication::Authentication() + : d(new Private) +{ + +} + +Solid::Control::Authentication::~Authentication() +{ + delete d; +} + +void Solid::Control::Authentication::setSecrets(const SecretMap &secrets) +{ + d->secrets = secrets; +} + +Solid::Control::Authentication::SecretMap Solid::Control::Authentication::secrets() const +{ + return d->secrets; +} + + + +/******************************************************************************/ + +Solid::Control::AuthenticationNone::AuthenticationNone() + : d(0) +{ + +} + +Solid::Control::AuthenticationNone::~AuthenticationNone() +{ + +} + + + +/******************************************************************************/ + +Solid::Control::AuthenticationWep::AuthenticationWep() + : d(new Private) +{ + +} + +Solid::Control::AuthenticationWep::~AuthenticationWep() +{ + delete d; +} + +void Solid::Control::AuthenticationWep::setMethod(WepMethod method) +{ + d->method = method; +} + +Solid::Control::AuthenticationWep::WepMethod Solid::Control::AuthenticationWep::method() const +{ + return d->method; +} + +void Solid::Control::AuthenticationWep::setType(WepType type) +{ + d->type = type; +} + +Solid::Control::AuthenticationWep::WepType Solid::Control::AuthenticationWep::type() const +{ + return d->type; +} + +void Solid::Control::AuthenticationWep::setKeyLength(int length) +{ + d->keyLength = length; +} + +int Solid::Control::AuthenticationWep::keyLength() const +{ + return d->keyLength; +} + +/******************************************************************************/ + +Solid::Control::AuthenticationWpa::AuthenticationWpa() + : d(new Private) +{ + +} + +Solid::Control::AuthenticationWpa::~AuthenticationWpa() +{ + delete d; +} + +void Solid::Control::AuthenticationWpa::setProtocol(WpaProtocol protocol) +{ + d->protocol = protocol; +} + +Solid::Control::AuthenticationWpa::WpaProtocol Solid::Control::AuthenticationWpa::protocol() const +{ + return d->protocol; +} + +void Solid::Control::AuthenticationWpa::setVersion(WpaVersion version) +{ + d->version = version; +} + +Solid::Control::AuthenticationWpa::WpaVersion Solid::Control::AuthenticationWpa::version() const +{ + return d->version; +} + +void Solid::Control::AuthenticationWpa::setKeyManagement(WpaKeyManagement mgmt) +{ + d->mgmt = mgmt; +} + +Solid::Control::AuthenticationWpa::WpaKeyManagement Solid::Control::AuthenticationWpa::keyManagement() const +{ + return d->mgmt; +} + +/******************************************************************************/ + +Solid::Control::AuthenticationWpaPersonal::AuthenticationWpaPersonal() + : d(0) +{ + +} + +Solid::Control::AuthenticationWpaPersonal::~AuthenticationWpaPersonal() +{ + +} + + + +/******************************************************************************/ + +Solid::Control::AuthenticationWpaEnterprise::AuthenticationWpaEnterprise() + : d(new Private) +{ + +} + +Solid::Control::AuthenticationWpaEnterprise::~AuthenticationWpaEnterprise() +{ + delete d; +} + +void Solid::Control::AuthenticationWpaEnterprise::setIdentity(const QString &identity) +{ + d->identity = identity; +} + +QString Solid::Control::AuthenticationWpaEnterprise::identity() const +{ + return d->identity; +} + +void Solid::Control::AuthenticationWpaEnterprise::setAnonIdentity(const QString &anonIdentity) +{ + d->anonIdentity = anonIdentity; +} + +QString Solid::Control::AuthenticationWpaEnterprise::anonIdentity() const +{ + return d->anonIdentity; +} + +void Solid::Control::AuthenticationWpaEnterprise::setCertClient(const QString &certClient) +{ + d->certClient = certClient; +} + +QString Solid::Control::AuthenticationWpaEnterprise::certClient() const +{ + return d->certClient; +} + +void Solid::Control::AuthenticationWpaEnterprise::setCertCA(const QString &certCA) +{ + d->certCA = certCA; +} + +QString Solid::Control::AuthenticationWpaEnterprise::certCA() const +{ + return d->certCA; +} + +void Solid::Control::AuthenticationWpaEnterprise::setCertPrivate(const QString &certPrivate) +{ + d->certPrivate = certPrivate; +} + +QString Solid::Control::AuthenticationWpaEnterprise::certPrivate() const +{ + return d->certPrivate; +} + + +void Solid::Control::AuthenticationWpaEnterprise::setMethod(EapMethod method) +{ + d->method = method; +} + +Solid::Control::AuthenticationWpaEnterprise::EapMethod Solid::Control::AuthenticationWpaEnterprise::method() const +{ + return d->method; +} + +void Solid::Control::AuthenticationWpaEnterprise::setIdPasswordKey(const QString &idPasswordKey) +{ + d->idPasswordKey = idPasswordKey; +} + +QString Solid::Control::AuthenticationWpaEnterprise::idPasswordKey() const +{ + return d->idPasswordKey; +} + +void Solid::Control::AuthenticationWpaEnterprise::setCertPrivatePasswordKey(const QString &certPrivatePasswordKey) +{ + d->certPrivatePasswordKey = certPrivatePasswordKey; +} + +QString Solid::Control::AuthenticationWpaEnterprise::certPrivatePasswordKey() const +{ + return d->certPrivatePasswordKey; +} + + + +Solid::Control::AuthenticationValidator::AuthenticationValidator() + : d(new Private) +{ +#if 0 + Ifaces::NetworkManager *backend = qobject_cast(NetworkManager::self().d->managerBackend()); + + if (backend) + { + d->backendObject = backend->createAuthenticationValidator(); + } +#endif +} + +Solid::Control::AuthenticationValidator::~AuthenticationValidator() +{ + delete d->backendObject; + delete d; +} + +bool Solid::Control::AuthenticationValidator::validate(const Solid::Control::Authentication *authentication) +{ + return_SOLID_CALL(Ifaces::AuthenticationValidator *, d->backendObject, false, validate(authentication)); +} + diff --git a/solid/control/authentication.h b/solid/control/authentication.h new file mode 100644 index 000000000..21a99a16d --- /dev/null +++ b/solid/control/authentication.h @@ -0,0 +1,309 @@ +/* This file is part of the KDE project + Copyright (C) 2006 Kevin Ottens + Copyright (C) 2007 Will Stephenson + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#ifndef SOLID_CONTROL_AUTHENTICATION_H +#define SOLID_CONTROL_AUTHENTICATION_H + +#include + +namespace Solid +{ +namespace Control +{ + /** + * Base class for wireless authentication schemes. No need to instantiate this + */ + class SOLIDCONTROL_EXPORT Authentication + { + public: + typedef QMap SecretMap; + + Authentication(); + virtual ~Authentication(); + + /** + * All the authentication's secrets are stored in this map. + * These can be plaintext passwords, hashed passwords, certificate passphrases + */ + void setSecrets(const SecretMap &); + /** + * retrieve the map containing secrets. + */ + SecretMap secrets() const; + + private: + class Private; + Private * const d; + }; + + /** + * This Authentication is a null authentication. Used for open networks + */ + class SOLIDCONTROL_EXPORT AuthenticationNone : public Authentication + { + public: + AuthenticationNone(); + virtual ~AuthenticationNone(); + + private: + class Private; + Private * const d; + }; + + /** + * WEP (Wired Equivalent Privacy) Authentication. + * Better than prayer for protecting your data, but not much. + */ + class SOLIDCONTROL_EXPORT AuthenticationWep : public Authentication + { + public: + /** + * Wep password type. WepAscii and WepPassphrase are both hashed to WepHex using + * standard algorithms, but are easier to remember. + */ + enum WepType { WepAscii, WepHex, WepPassphrase }; + /** + * Authentication schemes + * Open System has no authentication, if you have the encryption key, you are able to use the network + * Shared Key means that the station must know a secret key to authenticate to the network. + * Not sure if the same key is used for both Auth and Encryption though. + */ + enum WepMethod { WepOpenSystem, WepSharedKey }; + + AuthenticationWep(); + virtual ~AuthenticationWep(); + + /** + * Set the auth scheme in use + */ + void setMethod(WepMethod); + /** + * Get the auth scheme in use + */ + WepMethod method() const; + /** + * Set the password scheme in use + */ + void setType(WepType); + /** + * Get the password scheme in use + */ + WepType type() const; + /** + * Set the key length in bits + * Valid values are 40 or 64 (equivalent) + * 104 or 128 + * 192 + * 256 + * other values (rare) + */ + void setKeyLength(int); + /** + * Get the key length, in bits + */ + int keyLength() const; + + private: + class Private; + Private * const d; + }; + + /** + * AuthenticationWpa contains functionality shared by both Personal and Enterprise + * authentication flavors + */ + class SOLIDCONTROL_EXPORT AuthenticationWpa : public Authentication + { + public: + /** + * Possible Authentication schemes + */ + enum WpaProtocol { WpaAuto, WpaTkip, WpaCcmpAes, // WPA Personal only + WpaEap /* WPA Enterprise only */ }; + /** + * WPA Versions + */ + enum WpaVersion { Wpa1, Wpa2 }; + + /** + * WPA key management schemes + */ + enum WpaKeyManagement { WpaPsk, Wpa8021x }; + + AuthenticationWpa(); + virtual ~AuthenticationWpa(); + + /** + * Set the protocol in use + */ + void setProtocol(WpaProtocol); + /** + * Set the protocol in use + */ + WpaProtocol protocol() const; + + /** + * Set the WPA version + */ + void setVersion(WpaVersion); + /** + * Get the WPA version + */ + WpaVersion version() const; + + /** + * Set the key management scheme + */ + void setKeyManagement(WpaKeyManagement); + + /** + * Get the key management scheme + */ + WpaKeyManagement keyManagement() const; + + private: + class Private; + Private * const d; + }; + + /** + * WPA Personal authentication. + */ + class SOLIDCONTROL_EXPORT AuthenticationWpaPersonal : public AuthenticationWpa + { + public: + AuthenticationWpaPersonal(); + virtual ~AuthenticationWpaPersonal(); + + private: + class Private; + Private * const d; + }; + + /** + * WPA Enterprise + */ + class SOLIDCONTROL_EXPORT AuthenticationWpaEnterprise : public AuthenticationWpa + { + public: + /** + * Subtypes of Enterprise Authentication Protocol + */ + enum EapMethod { EapPeap, EapTls, EapTtls, EapMd5, EapMsChap, EapOtp, EapGtc }; + AuthenticationWpaEnterprise(); + virtual ~AuthenticationWpaEnterprise(); + + /** + * TODO: check with thoenig what this means - probably identity off one of the certs + */ + void setIdentity(const QString &); + /** + * TODO: check with thoenig what this means - probably identity off one of the certs + */ + QString identity() const; + + /** + * TODO: check with thoenig what this means - probably identity off one of the certs + */ + void setAnonIdentity(const QString &); + /** + * TODO: check with thoenig what this means - probably identity off one of the certs + */ + QString anonIdentity() const; + + /** + * Set path to the client certificate + */ + void setCertClient(const QString &); + /** + * Get path to the client certificate + */ + QString certClient() const; + /** + * Set path to the certification authority certificate + */ + void setCertCA(const QString &); + /** + * Get path to the certification authority certificate + */ + QString certCA() const; + + /** + * Set path to the private certificate + */ + void setCertPrivate(const QString &); + /** + * Get path to the private certificate + */ + QString certPrivate() const; + /** + * Set the EAP method + */ + void setMethod(EapMethod); + /** + * Get the EAP method + */ + EapMethod method() const; + /** + * Set the ID password key (helper method) + */ + void setIdPasswordKey(const QString &); + /** + * Set the ID password key (helper method) + */ + QString idPasswordKey() const; + + /** + * Set the private certificate password key (helper method) + */ + void setCertPrivatePasswordKey(const QString &); + /** + * Get the private certificate password key (helper method) + */ + QString certPrivatePasswordKey() const; + + private: + class Private; + Private * const d; + }; + + /** + * Utility class + * Contains a backend specific validator instance to validate authentication + * Can be used for example to authenticate user input as they type + */ + class SOLIDCONTROL_EXPORT AuthenticationValidator + { + public: + AuthenticationValidator(); + virtual ~AuthenticationValidator(); + /** + * Call this to check if an authentication is valid + * (All secrets present, passphrase length correct + */ + bool validate(const Authentication *); + private: + class Private; + Private * const d; + }; +} +} + +#endif diff --git a/solid/control/backends/CMakeLists.txt b/solid/control/backends/CMakeLists.txt new file mode 100644 index 000000000..876cfb00e --- /dev/null +++ b/solid/control/backends/CMakeLists.txt @@ -0,0 +1,3 @@ +add_subdirectory( fakenet ) +#add_subdirectory( fakebluetooth ) + diff --git a/solid/control/backends/fakebluetooth/CMakeLists.txt b/solid/control/backends/fakebluetooth/CMakeLists.txt new file mode 100644 index 000000000..dc2f487de --- /dev/null +++ b/solid/control/backends/fakebluetooth/CMakeLists.txt @@ -0,0 +1,31 @@ + +add_subdirectory( tests ) + +########### next target ############### + +set(solid_fakebluetooth_PART_SRCS + fakebluetoothinterface.cpp + fakebluetoothmanager.cpp + fakebluetoothremotedevice.cpp + fakebluetoothinputdevice.cpp + fakebluetoothsecurity.cpp +) + + +kde4_add_library(solid_fakebluetooth_static STATIC ${solid_fakebluetooth_PART_SRCS} ) +target_link_libraries(solid_fakebluetooth_static solidcontrolifaces ${KDE4_KDECORE_LIBS} ${QT_QTXML_LIBRARY} ) + +kde4_add_plugin(solid_fakebluetooth module.cpp ${solid_fakebluetooth_PART_SRCS}) + + +target_link_libraries(solid_fakebluetooth solidcontrolifaces ${KDE4_KDECORE_LIBS} ${QT_QTXML_LIBRARY} ) + +install(TARGETS solid_fakebluetooth DESTINATION ${PLUGIN_INSTALL_DIR} ) + + +########### install files ############### + +install( FILES solid_fakebluetooth.desktop DESTINATION ${SERVICES_INSTALL_DIR}/solidbackends ) +install( FILES fakebluetooth.xml DESTINATION ${DATA_INSTALL_DIR}/solidfakebluetoothbackend ) + + diff --git a/solid/control/backends/fakebluetooth/fakebluetooth.xml b/solid/control/backends/fakebluetooth/fakebluetooth.xml new file mode 100644 index 000000000..bb2072a5a --- /dev/null +++ b/solid/control/backends/fakebluetooth/fakebluetooth.xml @@ -0,0 +1,168 @@ + + + + 00:E0:98:DD:4E:FF + Bluetooth 1.1 + Build 525 + Cambridge Silicon Radio + Longshine + 1 + 120 + true + /org/kde/solid/fakebluetooth/hci0/FF:FF:FF:FF:FF:FF,/org/kde/solid/fakebluetooth/hci0/AA:BB:CC:DD:EE:FF + computer + uncategorized + networking,rendering,capturing,object,transfer,audio + Daniel's Laptop + FF:FF:FF:FF:FF:FF,AA:BB:CC:DD:EE:FF,FF:EE:DD:CC:BB:AA + true + true + FF:FF:FF:FF:FF:FF,AA:BB:CC:DD:EE:FF,FF:EE:DD:CC:BB:AA + FF:FF:FF:FF:FF:FF,AA:BB:CC:DD:EE:FF + + + EE:EE:EE:EE:EE:EE + true + Bluetooth 1.2 + Build 525 + Cambridge Silicon Radio + Nokia + computer + uncategorized + networking,rendering,capturing,object,transfer,audio + N800 + My N800 + 2007-03-25 02:45:00 GMT + 2007-03-25 00:40:00 GMT + true + + + + + + DD:DD:DD:DD:DD:DD + false + Bluetooth 1.1 + Build 525 + Cambridge Silicon Radio + Nokia + phone + cellular + networking,rendering,capturing,object,transfer,audio + Nokia 6230 + Company cellphone + 2007-03-25 02:45:00 GMT + 2007-03-25 00:40:00 GMT + false + + + + + + 00:04:61:81:74:0F + false + Bluetooth 1.1 + HCI 0x356 + Cambridge Silicon Radio + + peripheral + keyboard + + Bluetooth-Keyboard 81740F + Epox Test Keyboard + 2007-03-25 02:45:00 GMT + 2007-03-25 00:40:00 GMT + true + + + + + + 00:04:61:81:75:BE + false + Bluetooth 1.1 + HCI 0x356 + Cambridge Silicon Radio + + peripheral + pointing + + Bluetooth-Mouse 8175BE + Epox Test Mouse + 2007-03-25 02:45:00 GMT + 2007-03-25 00:40:00 GMT + false + + + + + + + + + + 00:00:98:DD:4E:00 + Bluetooth 1.1 + Build 525 + Cambridge Silicon Radio + Longshine + 2 + 120 + true + /org/kde/solid/fakebluetooth/hci0/FF:FF:FF:FF:FF:FF,/org/kde/solid/fakebluetooth/hci0/AA:BB:CC:DD:EE:FF + computer + uncategorized + networking,rendering,capturing,object,transfer,audio + Daniel's Laptop + FF:FF:FF:FF:FF:FF,AA:BB:CC:DD:EE:FF,FF:EE:DD:CC:BB:AA + true + true + FF:FF:FF:FF:FF:FF,AA:BB:CC:DD:EE:FF,FF:EE:DD:CC:BB:AA + FF:FF:FF:FF:FF:FF,AA:BB:CC:DD:EE:FF + + + + + FF:E0:98:DD:FF:FF + Bluetooth 1.2 + + Cambridge Silicon Radio + + 0 + 120 + true + /org/kde/solid/fakebluetooth/hci0/FF:FF:FF:FF:FF:FF,/org/kde/solid/fakebluetooth/hci0/AA:BB:CC:DD:EE:FF + computer + server + networking,rendering,capturing,object,transfer,audio + Daniel's Laptop + FF:FF:FF:FF:FF:FF,AA:BB:CC:DD:EE:FF,FF:EE:DD:CC:BB:AA + true + false + + + + + + AA:FF:EE:AA:FF:EE + Bluetooth 2.0 + Build 525 + Cambridge Silicon Radio + + 1 + 180 + true + /org/kde/solid/fakebluetooth/hci0/FF:FF:FF:FF:FF:FF,/org/kde/solid/fakebluetooth/hci0/AA:BB:CC:DD:EE:FF + computer + laptop + networking,rendering,capturing,object,transfer,audio + BlueZ (0) sugga + FF:FF:FF:FF:FF:FF,AA:BB:CC:DD:EE:FF,FF:EE:DD:CC:BB:AA + true + true + + + + + + diff --git a/solid/control/backends/fakebluetooth/fakebluetoothinputdevice.cpp b/solid/control/backends/fakebluetooth/fakebluetoothinputdevice.cpp new file mode 100644 index 000000000..350653920 --- /dev/null +++ b/solid/control/backends/fakebluetooth/fakebluetoothinputdevice.cpp @@ -0,0 +1,43 @@ +/* This file is part of the KDE project + Copyright (C) 2007 Daniel Gollub + + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#include + +#include "fakebluetoothinputdevice.h" + +#include + +FakeBluetoothInputDevice::FakeBluetoothInputDevice(const QMap & propertyMap, QObject * parent) + : Solid::Control::Ifaces::BluetoothInputDevice(parent), mPropertyMap(propertyMap) +{ + + mUbi = mPropertyMap["ubi"].toString(); + + kDebug() << "UBI: " << mUbi; + + mAddress = mPropertyMap["address"].toString(); + mConnected = mPropertyMap["connected"].toBool(); + mName = mPropertyMap["name"].toString(); +} + +FakeBluetoothInputDevice::~FakeBluetoothInputDevice() +{} + +#include "fakebluetoothinputdevice.moc" diff --git a/solid/control/backends/fakebluetooth/fakebluetoothinputdevice.h b/solid/control/backends/fakebluetooth/fakebluetoothinputdevice.h new file mode 100644 index 000000000..da76a17d7 --- /dev/null +++ b/solid/control/backends/fakebluetooth/fakebluetoothinputdevice.h @@ -0,0 +1,93 @@ +/* This file is part of the KDE project + Copyright (C) 2007 Daniel Gollub + + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#ifndef FAKE_BLUETOOTH_INPUTDEVICE_H +#define FAKE_BLUETOOTH_INPUTDEVICE_H + +#include +#include + +#include + +#include + +using namespace Solid::Control::Ifaces; + +class KDE_EXPORT FakeBluetoothInputDevice : public Solid::Control::Ifaces::BluetoothInputDevice +{ + Q_OBJECT + Q_INTERFACES(Solid::Control::Ifaces::BluetoothInputDevice) +public: + FakeBluetoothInputDevice(const QMap & propertyMap, + QObject *parent = 0); + virtual ~FakeBluetoothInputDevice(); + QString ubi() const + { + return mUbi; + } + bool isConnected() const + { + return mConnected; + } + QString address() const + { + return mAddress; + } + QString name() const + { + return mName; + } + QString productID() const + { + return mProductID; + } + QString vendorID() const + { + return mVendorID; + } + +private: + QString mUbi; + bool mConnected; + QString mAddress; + QString mName; + QString mVendorID; + QString mProductID; + +public Q_SLOTS: + void slotConnected() + { + mConnected = true; + } + void slotDisconnected() + { + mConnected = false; + } + +Q_SIGNALS: + void connected(); + void disconnected(); + +protected: + QMap mPropertyMap; + +}; + +#endif diff --git a/solid/control/backends/fakebluetooth/fakebluetoothinterface.cpp b/solid/control/backends/fakebluetooth/fakebluetoothinterface.cpp new file mode 100644 index 000000000..bc5de8768 --- /dev/null +++ b/solid/control/backends/fakebluetooth/fakebluetoothinterface.cpp @@ -0,0 +1,101 @@ +/* This file is part of the KDE project + Copyright (C) 2007 Daniel Gollub + + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#include +#include + +#include "fakebluetoothinterface.h" +#include "fakebluetoothremotedevice.h" + +#include + +FakeBluetoothInterface::FakeBluetoothInterface(const QMap & propertyMap, QObject * parent) + : Solid::Control::Ifaces::BluetoothInterface(parent), mPropertyMap(propertyMap) +{ + mAddress = mPropertyMap["address"].toString(); + mVersion = mPropertyMap["version"].toString(); + mRevision = mPropertyMap["revision"].toString(); + mManufacturer = mPropertyMap["manufacturer"].toString(); + mCompany = mPropertyMap["company"].toString(); + mMode = (Solid::Control::BluetoothInterface::Mode) mPropertyMap["mode"].toInt(); + mDiscoverableTimeout = mPropertyMap["discoverableTimeout"].toInt(); + mDiscoverable = mPropertyMap["isDiscoverable"].toBool(); + mConnections.append(mPropertyMap["connections"].toString()); + mMajorClass = mPropertyMap["majorClass"].toString(); + mMinorClasses.append(mPropertyMap["minorClasses"].toString()); + mMinorClass = mPropertyMap["minorClass"].toString(); + mServiceClasses.append(mPropertyMap["serviceClasses"].toString()); + mName = mPropertyMap["name"].toString(); + mBondings.append(mPropertyMap["bondings"].toString()); + mPeriodicDiscovery = mPropertyMap["isPeriodicDiscovery"].toBool(); + mPeriodicDiscoveryNameResolving = mPropertyMap["periodicDiscoveryNameResolving"].toBool(); + mRemoteDevices.append(mPropertyMap["remoteDevices"].toString()); + mRecentRemoteDevices.append(mPropertyMap["recentRemoteDevices"].toString()); + + mUbi = mPropertyMap["ubi"].toString(); +} + +FakeBluetoothInterface::~FakeBluetoothInterface() +{ + foreach (FakeBluetoothRemoteDevice *device, mBluetoothRemoteDevices) { + kDebug() << "DEVICE: " << device->ubi(); + delete device; + } + + mBluetoothRemoteDevices.clear(); +} + +QObject * FakeBluetoothInterface::createBluetoothRemoteDevice(const QString & ubi) +{ + if (mBluetoothRemoteDevices.contains(ubi)) { + kDebug() << "found " << ubi; + return mBluetoothRemoteDevices[ubi]; + } else { + kDebug() << "NOT found " << ubi; + return 0; + } +} + +QStringList FakeBluetoothInterface::bluetoothRemoteDevices() const +{ + kDebug() ; + return mBluetoothRemoteDevices.keys(); +} + +void FakeBluetoothInterface::discoverDevices() +{ + kDebug() ; + QTimer::singleShot(1000, this, + SIGNAL(remoteDeviceFound(QString("/org/kde/solid/fakebluetooth/hci0/EE:EE:EE:EE:EE:EE"), + 0, 99))); + QTimer::singleShot(5000, this, + SIGNAL(remoteDeviceFound(QString("/org/kde/solid/fakebluetooth/hci0/EE:FF:EE:FF:EE:FF"), + 0, 42))); + +} + +/*************************************/ + +void FakeBluetoothInterface::injectDevice(const QString &ubi , FakeBluetoothRemoteDevice *device) +{ + mBluetoothRemoteDevices.insert(ubi, device); +} + +#include "fakebluetoothinterface.moc" diff --git a/solid/control/backends/fakebluetooth/fakebluetoothinterface.h b/solid/control/backends/fakebluetooth/fakebluetoothinterface.h new file mode 100644 index 000000000..f7aa0c3b1 --- /dev/null +++ b/solid/control/backends/fakebluetooth/fakebluetoothinterface.h @@ -0,0 +1,231 @@ +/* This file is part of the KDE project + Copyright (C) 2007 Daniel Gollub + + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#ifndef FAKE_BLUETOOTH_INTERFACE_H +#define FAKE_BLUETOOTH_INTERFACE_H + +#include +#include + +#include + +#include + +#include + +#include "fakebluetoothremotedevice.h" + +using namespace Solid::Control::Ifaces; + +class KDE_EXPORT FakeBluetoothInterface : public Solid::Control::Ifaces::BluetoothInterface +{ + friend class FakeBluetoothManager; + Q_OBJECT + Q_INTERFACES(Solid::Control::Ifaces::BluetoothInterface) +public: + FakeBluetoothInterface(const QMap & propertyMap, + QObject *parent = 0); + virtual ~FakeBluetoothInterface(); + + QObject * createBluetoothRemoteDevice(const QString & ubi); + QStringList bluetoothRemoteDevices() const; + + QString ubi() const + { + return mUbi; + } + + QString address() const + { + kDebug() ; return mAddress; + } + QString version() const + { + return mVersion; + } + QString revision() const + { + return mRevision; + } + QString manufacturer() const + { + return mManufacturer; + } + QString company() const + { + return mCompany; + } + Solid::Control::BluetoothInterface::Mode mode() const + { + return mMode; + } + int discoverableTimeout() const + { + return mDiscoverableTimeout; + } + bool isDiscoverable() const + { + return mDiscoverable; + } + QStringList listConnections() const + { + return mConnections; + } + QString majorClass() const + { + return mMajorClass; + } + QStringList listAvailableMinorClasses() const + { + return mMinorClasses; + } + QString minorClass() const + { + return mMinorClass; + } + QStringList serviceClasses() const + { + return mServiceClasses; + } + QString name() const + { + return mName; + } + QString getRemoteName(const QString &) + { + return ""; + } + QStringList listBondings() const + { + return mBondings; + } + bool isPeriodicDiscoveryActive() const + { + return mPeriodicDiscovery; + } + bool isPeriodicDiscoveryNameResolvingActive() const + { + return mPeriodicDiscoveryNameResolving; + } + QStringList listRemoteDevices() const + { + return mRemoteDevices; + } + QStringList listRecentRemoteDevices(const QDateTime &) const + { + return mRecentRemoteDevices; + } + bool isTrusted(const QString& mac) + { + return true; + } + + void injectDevice(const QString &, FakeBluetoothRemoteDevice *); +private: + int mTimeout; + QString mName; + QString mUbi; + QString mAddress; + QString mVersion; + QString mRevision; + QString mManufacturer; + QString mCompany; + Solid::Control::BluetoothInterface::Mode mMode; + int mDiscoverableTimeout; + bool mDiscoverable; + QStringList mConnections; + QString mMajorClass; + QStringList mMinorClasses; + QString mMinorClass; + QStringList mServiceClasses; + QStringList mBondings; + bool mPeriodicDiscovery; + bool mPeriodicDiscoveryNameResolving; + QStringList mRemoteDevices; + QStringList mRecentRemoteDevices; + QString mSetTrusted; + QString mRemoveTrust; + + +public Q_SLOTS: + void setMode(const Solid::Control::BluetoothInterface::Mode mode) + { + mMode = mode; /* emit modeChanged(mMode); */ + } + void setDiscoverableTimeout(int timeout) + { + mTimeout = timeout; + } + void setMinorClass(const QString &minorClass) + { + mMinorClass = minorClass; + } + void setName(const QString &name) + { + mName = name; + } + void discoverDevices(); + void discoverDevicesWithoutNameResolving() + {} + void cancelDiscovery() + {} + void startPeriodicDiscovery() + {} + void stopPeriodicDiscovery() + {} + void setPeriodicDiscoveryNameResolving(bool resolving) + { + mPeriodicDiscoveryNameResolving = resolving; + } + void setTrusted(const QString& mac) + { + mSetTrusted = mac; + } + void removeTrust(const QString& mac) + { + mRemoveTrust = mac; + } + +Q_SIGNALS: + void modeChanged(Solid::Control::BluetoothInterface::Mode mode); + void discoverableTimeoutChanged(int timeout); + void minorClassChanged(const QString &minor); + void nameChanged(const QString &name); + void discoveryStarted(); + void discoveryCompleted(); + void remoteDeviceFound(const QString &ubi, int deviceClass, int rssi); + void remoteDeviceDisappeared(const QString &ubi); + + void remoteNameUpdated(const QString &address, const QString &name); + void remoteDeviceConnected(const QString &address); + void remoteDeviceDisconnected(const QString &address); + void trustAdded(const QString &address); + void trustRemoved(const QString &address); + void bondingCreated(const QString &address); + void bondingRemoved(const QString &address); +protected: + /* These methods are operations that are carried out by the manager + In a real backend they would be events coming up from the network layer */ + void injectBluetooth(const QString & ubi, FakeBluetoothRemoteDevice * device); + QMap mBluetoothRemoteDevices; + QMap mPropertyMap; +}; + +#endif diff --git a/solid/control/backends/fakebluetooth/fakebluetoothmanager.cpp b/solid/control/backends/fakebluetooth/fakebluetoothmanager.cpp new file mode 100644 index 000000000..3850d377f --- /dev/null +++ b/solid/control/backends/fakebluetooth/fakebluetoothmanager.cpp @@ -0,0 +1,222 @@ +/* This file is part of the KDE project + Copyright (C) 2007 Daniel Gollub + + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ +#include +#include +#include + +#include +#include + +#include "fakebluetoothmanager.h" + +FakeBluetoothManager::FakeBluetoothManager(QObject * parent, const QStringList &) : Solid::Control::Ifaces::BluetoothManager(parent) +{ + kDebug() ; + + mXmlFile = KStandardDirs::locate("data", "solidfakebackend/fakebluetooth.xml"); + +// QDBusConnection::sessionBus().registerObject("/org/kde/solid/fake", this, QDBusConnection::ExportNonScriptableSlots); + + parseBluetoothFile(); +} + +FakeBluetoothManager::FakeBluetoothManager(QObject * parent, const QStringList &, const QString &xmlFile) : Solid::Control::Ifaces::BluetoothManager(parent) +{ + kDebug() ; + mXmlFile = xmlFile; + if (mXmlFile.isEmpty()) { + kDebug() << "Falling back to installed bluetoothing xml"; + mXmlFile = KStandardDirs::locate("data", "solidfakebackend/fakebluetooth.xml"); + } + parseBluetoothFile(); +} + +FakeBluetoothManager::~FakeBluetoothManager() +{ + foreach (FakeBluetoothInterface *interface, mBluetoothInterfaces) { + delete interface; + } + + mBluetoothInterfaces.clear(); +} + +QStringList FakeBluetoothManager::bluetoothInterfaces() const +{ + return mBluetoothInterfaces.keys(); +} + +QObject * FakeBluetoothManager::createInterface(const QString & ubi) +{ + if (mBluetoothInterfaces.contains(ubi)) + return mBluetoothInterfaces[ubi]; + else + return 0; +} + +QString FakeBluetoothManager::defaultInterface() const +{ + return ""; +} + +void FakeBluetoothManager::parseBluetoothFile() +{ + QFile machineFile(mXmlFile); + if (!machineFile.open(QIODevice::ReadOnly)) { + kDebug() << "Error while opening " << mXmlFile; + return; + } + + QDomDocument fakeDocument; + QString error; + int line; + if (!fakeDocument.setContent(&machineFile, &error, &line)) { + kDebug() << "Error while creating the QDomDocument: " << error << " line: " << + line << endl; + machineFile.close(); + return; + } + machineFile.close(); + + kDebug() << "Parsing fake computer XML: " << mXmlFile; + QDomElement mainElement = fakeDocument.documentElement(); + QDomNode node = mainElement.firstChild(); + while (!node.isNull()) { + QDomElement tempElement = node.toElement(); + if (!tempElement.isNull() && tempElement.tagName() == QLatin1String("interface")) { + FakeBluetoothInterface *tempDevice = parseDeviceElement(tempElement); + if (tempDevice) { + mBluetoothInterfaces.insert(tempDevice->ubi(), tempDevice); +// Use the DeviceManager for now, the udi/ubi should +// emit deviceAdded(tempDevice->ubi()); + } + } + node = node.nextSibling(); + } +} + +FakeBluetoothInterface *FakeBluetoothManager::parseDeviceElement(const QDomElement &deviceElement) +{ + FakeBluetoothInterface *interface = 0; + QMap propertyMap; + QString ubi = deviceElement.attribute("ubi"); + propertyMap.insert("ubi", ubi); + kDebug() << "Listing device: " << ubi; + propertyMap.insert("ubi", QVariant(ubi)); + + QDomNode childNode = deviceElement.firstChild(); + while (!childNode.isNull()) { + QDomElement childElement = childNode.toElement(); + //kDebug() << "found child=" << childElement.tagName(); + if (!childElement.isNull() && childElement.tagName() == QLatin1String("property")) { + QString propertyKey; + QVariant propertyValue; + + propertyKey = childElement.attribute("key"); + propertyValue = QVariant(childElement.text()); + // kDebug() << "Got property key=" << propertyKey << ", value=" << propertyValue.toString(); + propertyMap.insert(propertyKey, propertyValue); + } else if (!childElement.isNull() && childElement.tagName() == QLatin1String("device")) { + QString ubi = childElement.attribute("ubi"); + kDebug() << "Listing properties: " << ubi; + FakeBluetoothRemoteDevice * remoteDevice = new FakeBluetoothRemoteDevice(parseBluetoothElement(childElement)); + mBluetoothRemoteDevices.insert(ubi, remoteDevice); + } + childNode = childNode.nextSibling(); + } + //kDebug() << "Done listing. "; + + kDebug() << "Creating FakeBluetoothInterface for " << ubi; + interface = new FakeBluetoothInterface(propertyMap); + + // Inject Remote devices.... + foreach (FakeBluetoothRemoteDevice *device, mBluetoothRemoteDevices) { + kDebug() << "Injecting " << device->name(); + interface->injectDevice(device->ubi(), device); + } + + mBluetoothRemoteDevices.clear(); + + return interface; +} + +QMap FakeBluetoothManager::parseBluetoothElement(const QDomElement &deviceElement) +{ + QMap propertyMap; + + QString ubi = deviceElement.attribute("ubi"); + propertyMap.insert("ubi", ubi); + + QDomNode propertyNode = deviceElement.firstChild(); + while (!propertyNode.isNull()) { + QDomElement propertyElement = propertyNode.toElement(); + if (!propertyElement.isNull() && propertyElement.tagName() == QLatin1String("property")) { + QString propertyKey; + QVariant propertyValue; + + propertyKey = propertyElement.attribute("key"); + propertyValue = QVariant(propertyElement.text()); +// kDebug() << "Got property key=" << propertyKey << ", value=" << propertyValue.toString(); + propertyMap.insert(propertyKey, propertyValue); + } + + propertyNode = propertyNode.nextSibling(); + } + return propertyMap; +} + +FakeBluetoothInterface *FakeBluetoothManager::createBluetoothInterface(const QString &ubi) +{ + if (mBluetoothInterfaces.contains(ubi)) + return mBluetoothInterfaces[ubi]; + else + return 0; +} + +QStringList FakeBluetoothManager::bluetoothInputDevices() const +{ + return QStringList(); +} + +FakeBluetoothInputDevice *FakeBluetoothManager::createBluetoothInputDevice(const QString &ubi) +{ + if (mBluetoothInputDevices.contains(ubi)) + return mBluetoothInputDevices[ubi]; + else + return 0; +} + +KJob *FakeBluetoothManager::setupInputDevice(const QString & /*ubi */) +{ + // TODO + return NULL; +} +Solid::Control::Ifaces::BluetoothSecurity *FakeBluetoothManager::security(const QString &/*interface*/) +{ + return NULL; +} + +void FakeBluetoothManager::removeInputDevice(const QString & /*ubi */) +{ + //TODO +} + + +#include "fakebluetoothmanager.moc" + diff --git a/solid/control/backends/fakebluetooth/fakebluetoothmanager.h b/solid/control/backends/fakebluetooth/fakebluetoothmanager.h new file mode 100644 index 000000000..24114ca9f --- /dev/null +++ b/solid/control/backends/fakebluetooth/fakebluetoothmanager.h @@ -0,0 +1,66 @@ +/* This file is part of the KDE project + Copyright (C) 2007 Daniel Gollub + + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#ifndef FAKE_BLUETOOTH_MANAGER_H +#define FAKE_BLUETOOTH_MANAGER_H + +#include +#include + +#include + +#include +#include "fakebluetoothinterface.h" +#include "fakebluetoothinputdevice.h" +#include "fakebluetoothsecurity.h" + +class QDomElement; + +class KDE_EXPORT FakeBluetoothManager : public Solid::Control::Ifaces::BluetoothManager +{ + Q_OBJECT +public: + FakeBluetoothManager(QObject * parent, const QStringList & args); + FakeBluetoothManager(QObject * parent, const QStringList & args, const QString & xmlFile); + ~FakeBluetoothManager(); + QStringList bluetoothInterfaces() const; + FakeBluetoothInterface *createBluetoothInterface(const QString &); + QString defaultInterface() const; + QObject *createInterface(const QString &); + + QStringList bluetoothInputDevices() const; + FakeBluetoothInputDevice *createBluetoothInputDevice(const QString &ubi); + KJob *setupInputDevice(const QString &ubi); + Solid::Control::Ifaces::BluetoothSecurity * security(const QString &interface); +public Q_SLOTS: + void removeInputDevice(const QString & ubi); + +private: + void parseBluetoothFile(); + FakeBluetoothInterface *parseDeviceElement(const QDomElement &deviceElement); + QMap parseBluetoothElement(const QDomElement &deviceElement); + + QMap mBluetoothInterfaces; + QMap mBluetoothInputDevices; + QMap mBluetoothRemoteDevices; + QString mXmlFile; +}; + +#endif diff --git a/solid/control/backends/fakebluetooth/fakebluetoothremotedevice.cpp b/solid/control/backends/fakebluetooth/fakebluetoothremotedevice.cpp new file mode 100644 index 000000000..9d3c75c3c --- /dev/null +++ b/solid/control/backends/fakebluetooth/fakebluetoothremotedevice.cpp @@ -0,0 +1,66 @@ +/* This file is part of the KDE project + Copyright (C) 2007 Daniel Gollub + + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#include + +#include "fakebluetoothmanager.h" +#include "fakebluetoothinterface.h" +#include "fakebluetoothremotedevice.h" + +#include + +FakeBluetoothRemoteDevice::FakeBluetoothRemoteDevice(const QMap & propertyMap, QObject * parent) + : Solid::Control::Ifaces::BluetoothRemoteDevice(parent), mPropertyMap(propertyMap) +{ + + mUbi = mPropertyMap["ubi"].toString(); + + kDebug() << "UBI: " << mUbi; + + mAddress = mPropertyMap["address"].toString(); + mConnected = mPropertyMap["connected"].toBool(); + mVersion = mPropertyMap["version"].toString(); + mRevision = mPropertyMap["revision"].toString(); + mManufacturer = mPropertyMap["manufacturer"].toString(); + mCompany = mPropertyMap["company"].toString(); + mMajorClass = mPropertyMap["majorClass"].toString(); + mMinorClass = mPropertyMap["minorClass"].toString(); + mServiceClass.append(mPropertyMap["serviceClasses"].toString()); + mName = mPropertyMap["name"].toString(); + mAlias = mPropertyMap["alias"].toString(); + mLastSeen = mPropertyMap["lastSeen"].toString(); + mLastUsed = mPropertyMap["lastUsed"].toString(); + mBonded = mPropertyMap["bonded"].toBool(); + mPinCodeLength = mPropertyMap["pinCodeLength"].toInt(); + mEncryptionKeySize = mPropertyMap["encryptionKeySize"].toInt(); + +} + +FakeBluetoothRemoteDevice::~FakeBluetoothRemoteDevice() +{} + +// TODO +KJob *FakeBluetoothRemoteDevice::createBonding() +{ + mBonded = true; + return NULL; +} + +#include "fakebluetoothremotedevice.moc" diff --git a/solid/control/backends/fakebluetooth/fakebluetoothremotedevice.h b/solid/control/backends/fakebluetooth/fakebluetoothremotedevice.h new file mode 100644 index 000000000..9f49cbcac --- /dev/null +++ b/solid/control/backends/fakebluetooth/fakebluetoothremotedevice.h @@ -0,0 +1,175 @@ +/* This file is part of the KDE project + Copyright (C) 2007 Daniel Gollub + + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#ifndef FAKE_BLUETOOTH_REMOTEDEVICE_H +#define FAKE_BLUETOOTH_REMOTEDEVICE_H + +#include +#include + +#include + +#include + +using namespace Solid::Control::Ifaces; + +class KDE_EXPORT FakeBluetoothRemoteDevice : public Solid::Control::Ifaces::BluetoothRemoteDevice +{ + Q_OBJECT + Q_INTERFACES(Solid::Control::Ifaces::BluetoothRemoteDevice) +public: + FakeBluetoothRemoteDevice(const QMap & propertyMap, + QObject *parent = 0); + virtual ~FakeBluetoothRemoteDevice(); + QString ubi() const + { + return mUbi; + } + QString address() const + { + return mAddress; + } + bool isConnected() const + { + return mConnected; + } + QString version() const + { + return mVersion; + } + QString revision() const + { + return mRevision; + } + QString manufacturer() const + { + return mManufacturer; + } + QString company() const + { + return mCompany; + } + QString majorClass() const + { + return mMajorClass; + } + QString minorClass() const + { + return mMinorClass; + } + QStringList serviceClasses() const + { + return mServiceClass; + } + QString name() const + { + return mName; + } + QString alias() const + { + return mAlias; + } + QString lastSeen() const + { + return mLastSeen; + } + QString lastUsed() const + { + return mLastUsed; + } + bool hasBonding() const + { + return mBonded; + } + int pinCodeLength() const + { + return mPinCodeLength; + } + int encryptionKeySize() const + { + return mEncryptionKeySize; + } + KJob *createBonding(); + +private: + QString mUbi; + QString mAddress; + bool mConnected; + QString mVersion; + QString mRevision; + QString mManufacturer; + QString mCompany; + QString mMajorClass; + QString mMinorClass; + QStringList mServiceClass; + QString mName; + QString mAlias; + QString mLastSeen; + QString mLastUsed; + bool mBonded; + int mPinCodeLength; + int mEncryptionKeySize; + bool servicesFound; + +public Q_SLOTS: + void setAlias(const QString &alias) + { + mAlias = alias; + } + void clearAlias() + { + mAlias = ""; + } + void disconnect() + { + mConnected = false; + } + void cancelBondingProcess() + {} + void removeBonding() + { + mBonded = false; + } + void serviceHandles(const QString &) const + { + + } + void serviceRecordAsXml(uint ) const + { + } +Q_SIGNALS: + void classChanged(uint devClass); + void nameChanged(const QString &name); + void nameResolvingFailed(); + void aliasChanged(const QString &alias); + void aliasCleared(); + void connected(); + void requestDisconnection(); + void disconnected(); + void bondingCreated(); + void bondingRemoved(); + void serviceRecordXmlAvailable(const QString &ubi, const QString &record); + void serviceHandlesAvailable(const QString &ubi, const QList &handles); +protected: + QMap mPropertyMap; + +}; + +#endif diff --git a/solid/control/backends/fakebluetooth/fakebluetoothsecurity.cpp b/solid/control/backends/fakebluetooth/fakebluetoothsecurity.cpp new file mode 100644 index 000000000..7f1c17057 --- /dev/null +++ b/solid/control/backends/fakebluetooth/fakebluetoothsecurity.cpp @@ -0,0 +1,31 @@ +/* This file is part of the KDE project + Copyright (C) 2007 Juan González + + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ +#include "fakebluetoothsecurity.h" + +void FakeBluetoothSecurity::setPasskeyAgent(Solid::Control::BluetoothPasskeyAgent * agent) +{ + Q_UNUSED(agent) +} + +void FakeBluetoothSecurity::setAuthorizationAgent(Solid::Control::BluetoothAuthorizationAgent * agent) +{ + Q_UNUSED(agent) +} + +#include "fakebluetoothsecurity.moc" diff --git a/solid/control/backends/fakebluetooth/fakebluetoothsecurity.h b/solid/control/backends/fakebluetooth/fakebluetoothsecurity.h new file mode 100644 index 000000000..c864b5233 --- /dev/null +++ b/solid/control/backends/fakebluetooth/fakebluetoothsecurity.h @@ -0,0 +1,34 @@ +/* This file is part of the KDE project + Copyright (C) 2007 Juan González + + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ +#ifndef __FAKE_BLUETOOTH_SECURITY__ +#define __FAKE_BLUETOOTH_SECURITY__ + +#include +#include + +class KDE_EXPORT FakeBluetoothSecurity : public Solid::Control::Ifaces::BluetoothSecurity +{ + Q_OBJECT + public Q_SLOTS: + void setPasskeyAgent(Solid::Control::BluetoothPasskeyAgent *agent); + void setAuthorizationAgent(Solid::Control::BluetoothAuthorizationAgent *agent); +}; + +#endif diff --git a/solid/control/backends/fakebluetooth/module.cpp b/solid/control/backends/fakebluetooth/module.cpp new file mode 100644 index 000000000..2bba3a69a --- /dev/null +++ b/solid/control/backends/fakebluetooth/module.cpp @@ -0,0 +1,28 @@ +/* This file is part of the KDE project + Copyright (C) 2007 Daniel Gollub + + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#include "fakebluetoothmanager.h" + +// KDE includes +#include + +typedef KGenericFactory FakeBluetoothBackendFactory; +K_EXPORT_COMPONENT_FACTORY(solid_fake_bluetoothmgmt, FakeBluetoothBackendFactory("fakebluetoothbackend")) + diff --git a/solid/control/backends/fakebluetooth/solid_fakebluetooth.desktop b/solid/control/backends/fakebluetooth/solid_fakebluetooth.desktop new file mode 100644 index 000000000..e67b995ce --- /dev/null +++ b/solid/control/backends/fakebluetooth/solid_fakebluetooth.desktop @@ -0,0 +1,128 @@ +[Desktop Entry] +Type=Service +X-KDE-ServiceTypes=SolidBluetoothManager +X-KDE-Library=solid_fakebluetooth +InitialPreference=10 +Icon=preferences-system-bluetooth +Name=Fake Bluetooth +Name[af]=Bluetooth-nabootsing +Name[be]=Падробка пад Bluetooth +Name[be@latin]=Udavany „Bluetooth” +Name[bg]=Фалшив Bluetooth +Name[ca]=Bluetooth fals +Name[csb]=Falszëwi Bluetooth +Name[da]=Falsk Bluetooth +Name[de]=Bluetooth (Dummy) +Name[el]=Πλαστό Bluetooth +Name[eo]=Ŝajnigita Bluetooth +Name[es]=Bluetooth falso +Name[et]=Liba-Bluetooth +Name[eu]=Bluetooth faltsua +Name[fa]=بلوتوث جعلی +Name[fi]=Väärä Bluetooth +Name[fr]=Bluetooth factice +Name[fy]=Ferfalske bluetooth +Name[ga]=Bluetooth Bréige +Name[gl]=Bluetooth falso +Name[gu]=ખોટું બ્લ્યુટૂથ +Name[he]=‏Bluetooth מזוייף +Name[hi]=नक़ली ब्लूटूथ +Name[hu]=Bluetooth (imitáció) +Name[is]=Fölsk Blátönn +Name[ja]=疑似 Bluetooth +Name[kk]=Жалған Bluetooth +Name[km]=ប៊្លូធូស​​ក្លែងក្លាយ +Name[kn]=ನಕಲಿ ಬ್ಲೂಟೂತ್ +Name[ko]=가짜 블루투스 +Name[lt]=Netikras Bluetooth +Name[lv]=Neīsts Bluetooth +Name[mk]=Лажен Bluetooth +Name[ml]=ഫെയിക്ക് ബ്ലൂടൂത് +Name[mr]=बनावटी ब्लूटूथ +Name[nb]=Falsk Bluetooth +Name[nds]=Bluetooth (Platzholler) +Name[ne]=नक्कली ब्लुटुथ +Name[nl]=Nep Bluetooth +Name[nn]=Falsk Bluetooth +Name[pa]=ਫ਼ਰਜ਼ੀ ਬਲਿਊਟੁੱਥ +Name[pl]=Nieprawdziwy Bluetooth +Name[pt]=Bluetooth Falso +Name[pt_BR]=Bluetooth Falso +Name[ro]=Bluetooth fals +Name[ru]=Фальшивый Bluetooth +Name[se]=Mahkáš-Bluetooth +Name[sl]=Lažni Bluetooth +Name[sr]=Лажни блутут +Name[sr@latin]=Lažni Bluetooth +Name[sv]=Blåtandstest +Name[te]=నకిలీ బ్లూటూత్ +Name[th]=บลูทูธเทียม +Name[tr]=Sahte Bluetooth +Name[uk]=Фальшивий Bluetooth +Name[vi]=Bluetooth giả +Name[wa]=Fås Bluetooth +Name[x-test]=xxFake Bluetoothxx +Name[zh_CN]=虚假蓝牙 +Name[zh_TW]=Fake 藍芽 +Comment=Fake Bluetooth Management +Comment[af]=Bluetooth-nabootsing beheer +Comment[be]=Кіраванне падробным Buletooth +Comment[be@latin]=Kiravańnie udavanym „Bluetooth” +Comment[bg]=Фалшив Bluetooth +Comment[ca]=Gestió del bluetooth fals +Comment[csb]=Sprôwianié falszëwim Bluetoothã +Comment[da]=Håndtering af falsk Bluetooth +Comment[de]=Bluetooth-Verwaltung (Dummy) +Comment[el]=Διαχείριση πλαστού Bluetooth +Comment[eo]=Administrilo de ŝajnigita Bluetooth +Comment[es]=Gestión de Bluetooth falsa +Comment[et]=Liba-Bluetoothi haldur +Comment[eu]=Bluetooth faltsuaren kudeaketa +Comment[fa]=مدیریت بلوتوث جعلی +Comment[fi]=Väärä Bluetooth-hallinta +Comment[fr]=Gestion Bluetooth factice +Comment[fy]=Ferfalske bluetooth behear +Comment[ga]=Bainisteoireacht Bluetooth Bréige +Comment[gl]=Xestión de Bluetooth falso +Comment[gu]=ખોટું બ્લ્યુટૂથ વ્યવસ્થાપક +Comment[he]=ניהול Bluetooth מזוייף +Comment[hi]=नक़ली ब्लूटूथ प्रबंधन +Comment[hr]=Bluetooth upravljanje +Comment[hu]=Bluetooth-kezelés (imitáció) +Comment[is]=Fölsk Blátannarstýring +Comment[it]=Gestione di un falso Bluetooth +Comment[ja]=疑似 Bluetooth の管理 +Comment[kk]=Жалған Bluetooth-ды басқару +Comment[km]=ការ​គ្រប់គ្រង​ប៊្លូធូស​ក្លែងក្លាយ​ +Comment[kn]=ನಕಲಿ ಬ್ಲೂಟೂತ್ ವ್ಯವಸ್ಥಾಪನೆ +Comment[ko]=가짜 블루투스 관리 +Comment[lt]=Netikro Bluetooth tvarkymas +Comment[lv]=Neīsts Bluetooth pārvaldnieks +Comment[ml]=ഫെയിക്ക് ബ്ലൂടുത് മാനേജ്മെന്റ് +Comment[mr]=बनावटी ब्लूटूथ व्यवस्थापन +Comment[nb]=Falsk Bluetooth-styring +Comment[nds]=Bluetooth-Pleger (Platzholler) +Comment[ne]=नक्कली ब्लुटुथ व्यवस्थापन +Comment[nl]=Nep Bluetooth-beheer +Comment[nn]=Falsk Bluetooth-handtering +Comment[pa]=ਫ਼ਰਜ਼ੀ ਬਲਿਊਟੁੱਥ ਮੈਨਿਜਮੈਂਟ +Comment[pl]=Nieprawdziwe zarządzanie Bluetooth +Comment[pt]=Gestão do Bluetooth Falso +Comment[pt_BR]=Gerenciamento de Bluetooth Falso +Comment[ro]=Management Bluetooth fals +Comment[ru]=Фальшивое управление Bluetooth +Comment[se]=Mahkáš-Bluetooth-gieđahallan +Comment[sl]=Upravljanje z lažnim Bluetooth +Comment[sr]=Управљање лажним блутутом +Comment[sr@latin]=Upravljanje lažnim Bluetoothom +Comment[sv]=Blåtandshanteringstest +Comment[te]=నకిలీ బ్లూటూత్ నిర్వహణ +Comment[tg]=Идоракунии Fake Bluetooth +Comment[th]=การจัดการบลูทูธเทียม +Comment[tr]=Sahte Bluetooth Yönetimi +Comment[uk]=Керування фальшивим Bluetooth +Comment[vi]=Quản lý Bluetooth giả +Comment[wa]=Manaedmint di Fås Bluetooth +Comment[x-test]=xxFake Bluetooth Managementxx +Comment[zh_CN]=虚假蓝牙管理 +Comment[zh_TW]=Fake 藍芽管理 diff --git a/solid/control/backends/fakebluetooth/tests/CMakeLists.txt b/solid/control/backends/fakebluetooth/tests/CMakeLists.txt new file mode 100644 index 000000000..876626b0d --- /dev/null +++ b/solid/control/backends/fakebluetooth/tests/CMakeLists.txt @@ -0,0 +1,19 @@ +set( EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR} ) + +include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/.. ) + +########### next target ############### + +set(fakebluetoothtest_SRCS fakebluetoothtest.cpp ) + + +kde4_add_unit_test(fakebluetoothtest ${fakebluetoothtest_SRCS}) + +target_link_libraries(fakebluetoothtest solid_fakebluetooth_static solidcontrolifaces ${KDE4_KDECORE_LIBS} ${QT_QTTEST_LIBRARY} ) +add_definitions(-DTEST_DATA="\\"${CMAKE_CURRENT_SOURCE_DIR}/../fakebluetooth.xml\\"") + + +########### install files ############### + + + diff --git a/solid/control/backends/fakebluetooth/tests/fakebluetoothtest.cpp b/solid/control/backends/fakebluetooth/tests/fakebluetoothtest.cpp new file mode 100644 index 000000000..86c55e4be --- /dev/null +++ b/solid/control/backends/fakebluetooth/tests/fakebluetoothtest.cpp @@ -0,0 +1,72 @@ +/* This file is part of the KDE project + Copyright (C) 2006 Will Stephenson + Copyright (C) 2007 Daniel Gollub + + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +// KDE-QTestLib include +#include + +#include "fakebluetoothmanager.h" + +#include "fakebluetoothtest.h" + +QTEST_KDEMAIN_CORE(FakeBluetooth_Test) + +void FakeBluetooth_Test::testFakeBluetooth() +{ + FakeBluetoothManager *fbm = new FakeBluetoothManager(0, QStringList(), TEST_DATA); + QVERIFY(!fbm->bluetoothInterfaces().isEmpty()); + + // Bluetooth Interface + FakeBluetoothInterface *interface = static_cast(fbm->createBluetoothInterface("/org/kde/solid/fakebluetooth/hci0")); + + QCOMPARE(interface->ubi(), QString("/org/kde/solid/fakebluetooth/hci0")); + QCOMPARE(interface->address(), QString("00:E0:98:DD:4E:FF")); + QCOMPARE(interface->version(), QString("Bluetooth 1.1")); + QCOMPARE(interface->revision(), QString("Build 525")); + QCOMPARE(interface->name(), QString("Daniel's Laptop")); + + interface->setName("CrashDummy"); + QCOMPARE(interface->name(), QString("CrashDummy")); + + // Bluetooth Remote Devices + QCOMPARE(interface->bluetoothRemoteDevices().count(), 4); + kDebug() << "REMOTE DEVICES: " << interface->bluetoothRemoteDevices(); + FakeBluetoothRemoteDevice *device = + static_cast(interface->createBluetoothRemoteDevice("/org/kde/solid/fakebluetooth/hci0/EE:EE:EE:EE:EE:EE")); + + QCOMPARE(device->name(), QString("N800")); + QCOMPARE(device->alias(), QString("My N800")); + + // Bluetooth Interface + interface = static_cast(fbm->createBluetoothInterface("/org/kde/solid/fakebluetooth/XXX")); + + QCOMPARE(interface->ubi(), QString("/org/kde/solid/fakebluetooth/XXX")); + QCOMPARE(interface->address(), QString("AA:FF:EE:AA:FF:EE")); + QCOMPARE(interface->version(), QString("Bluetooth 2.0")); + QCOMPARE(interface->company(), QString("")); + QCOMPARE(interface->name(), QString("BlueZ (0) sugga")); + + interface->setName("CrashDummy2"); + QCOMPARE(interface->name(), QString("CrashDummy2")); + + delete fbm; +} + +#include "fakebluetoothtest.moc" diff --git a/solid/control/backends/fakebluetooth/tests/fakebluetoothtest.h b/solid/control/backends/fakebluetooth/tests/fakebluetoothtest.h new file mode 100644 index 000000000..3439d6c86 --- /dev/null +++ b/solid/control/backends/fakebluetooth/tests/fakebluetoothtest.h @@ -0,0 +1,34 @@ +/* This file is part of the KDE project + Copyright (C) 2006 Will Stephenson + Copyright (C) 2006 Daniel Gollub + + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#ifndef FAKEBACKENDTEST_H +#define FAKEBACKENDTEST_H + +#include + +class FakeBluetooth_Test : public QObject +{ + Q_OBJECT +private slots: + void testFakeBluetooth(); +}; + +#endif diff --git a/solid/control/backends/fakenet/CMakeLists.txt b/solid/control/backends/fakenet/CMakeLists.txt new file mode 100644 index 000000000..519eda018 --- /dev/null +++ b/solid/control/backends/fakenet/CMakeLists.txt @@ -0,0 +1,31 @@ + +add_subdirectory( tests ) + +########### next target ############### + +set(solid_fakenet_PART_SRCS + fakeaccesspoint.cpp + fakenetworkinterface.cpp + fakewirednetworkinterface.cpp + fakewirelessnetworkinterface.cpp + fakenetworkmanager.cpp +) + + +kde4_add_library(solid_fakenet_static STATIC ${solid_fakenet_PART_SRCS} ) +target_link_libraries(solid_fakenet_static solidcontrol solidcontrolifaces ${KDE4_KDECORE_LIBS} ${QT_QTXML_LIBRARY} ) + +kde4_add_plugin(solid_fakenet module.cpp ${solid_fakenet_PART_SRCS}) + + +target_link_libraries(solid_fakenet solidcontrol solidcontrolifaces ${KDE4_KDECORE_LIBS} ${QT_QTXML_LIBRARY} ) + +install(TARGETS solid_fakenet DESTINATION ${PLUGIN_INSTALL_DIR} ) + + +########### install files ############### + +install( FILES solid_fakenet.desktop DESTINATION ${SERVICES_INSTALL_DIR}/solidbackends ) +install( FILES fakenetworking.xml DESTINATION ${DATA_INSTALL_DIR}/solidfakenetbackend ) + + diff --git a/solid/control/backends/fakenet/fakeaccesspoint.cpp b/solid/control/backends/fakenet/fakeaccesspoint.cpp new file mode 100644 index 000000000..eda6a00c4 --- /dev/null +++ b/solid/control/backends/fakenet/fakeaccesspoint.cpp @@ -0,0 +1,133 @@ +/* +Copyright 2008 Will Stephenson + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) version 3, or any +later version accepted by the membership of KDE e.V. (or its +successor approved by the membership of KDE e.V.), which shall +act as a proxy defined in Section 6 of version 3 of the license. + +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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library. If not, see . +*/ + +#include "fakeaccesspoint.h" + +FakeAccessPoint::FakeAccessPoint( const QMap & propertyMap, + QObject * parent) +: Solid::Control::Ifaces::AccessPoint( parent ), mPropertyMap(propertyMap) +{ +} + +FakeAccessPoint::~FakeAccessPoint() +{ + +} + +// PHY stuff +QString FakeAccessPoint::uni() const +{ + return mPropertyMap["uni"].toString(); +} + + +QString FakeAccessPoint::ssid() const +{ + return mPropertyMap["ssid"].toString(); +} + + +uint FakeAccessPoint::frequency() const +{ + return mPropertyMap["frequency"].toUInt(); +} + +QString FakeAccessPoint::hardwareAddress() const +{ + return mPropertyMap["hwaddress"].toString(); +} + +uint FakeAccessPoint::maxBitRate() const +{ + return mPropertyMap["maxbitrate"].toUInt(); +} + +int FakeAccessPoint::signalStrength() const +{ + return mPropertyMap["signalstrength"].toInt(); +} + +Solid::Control::AccessPoint::WpaFlags FakeAccessPoint::wpaFlags() const +{ + return wpaPropsToFlags( "wpaflags" ); +} + +Solid::Control::AccessPoint::WpaFlags FakeAccessPoint::rsnFlags() const +{ + return wpaPropsToFlags( "rsnflags" ); +} + +Solid::Control::AccessPoint::WpaFlags FakeAccessPoint::wpaPropsToFlags( const QString & property ) const +{ + QStringList capStrings = mPropertyMap[property].toStringList(); + + Solid::Control::AccessPoint::WpaFlags caps = 0; + if (capStrings.contains("pairwep40")) + caps |= Solid::Control::AccessPoint::PairWep40; + if (capStrings.contains("pairweb104")) + caps |= Solid::Control::AccessPoint::PairWep104; + if (capStrings.contains("pairtkip")) + caps |= Solid::Control::AccessPoint::PairTkip; + if (capStrings.contains("pairccmp")) + caps |= Solid::Control::AccessPoint::PairCcmp; + if (capStrings.contains("groupwep40")) + caps |= Solid::Control::AccessPoint::GroupWep40; + if (capStrings.contains("groupweb104")) + caps |= Solid::Control::AccessPoint::GroupWep104; + if (capStrings.contains("grouptkip")) + caps |= Solid::Control::AccessPoint::GroupTkip; + if (capStrings.contains("groupccmp")) + caps |= Solid::Control::AccessPoint::GroupCcmp; + if (capStrings.contains("keypsk")) + caps |= Solid::Control::AccessPoint::KeyMgmtPsk; + if (capStrings.contains("key8021x")) + caps |= Solid::Control::AccessPoint::KeyMgmt8021x; + return caps; +} + +Solid::Control::AccessPoint::Capabilities FakeAccessPoint::capabilities() const +{ + //TODO + QStringList capStrings = mPropertyMap["capabilities"].toStringList(); + + Solid::Control::AccessPoint::Capabilities caps = 0; + if (capStrings.contains("privacy")) + caps |= Solid::Control::AccessPoint::Privacy; + return caps; +} + +Solid::Control::WirelessNetworkInterface::OperationMode FakeAccessPoint::mode() const +{ + QString modeName = mPropertyMap["mode"].toString(); + + if (modeName == "adhoc") + return Solid::Control::WirelessNetworkInterface::Adhoc; + else if (modeName == "managed") + return Solid::Control::WirelessNetworkInterface::Managed; + else if (modeName == "master") + return Solid::Control::WirelessNetworkInterface::Master; + else if (modeName == "repeater") + return Solid::Control::WirelessNetworkInterface::Repeater; + else + return Solid::Control::WirelessNetworkInterface::Unassociated; +} + +#include "fakeaccesspoint.moc" + diff --git a/solid/control/backends/fakenet/fakeaccesspoint.h b/solid/control/backends/fakenet/fakeaccesspoint.h new file mode 100644 index 000000000..1515087a7 --- /dev/null +++ b/solid/control/backends/fakenet/fakeaccesspoint.h @@ -0,0 +1,62 @@ +/* +Copyright 2008 Will Stephenson + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) version 3, or any +later version accepted by the membership of KDE e.V. (or its +successor approved by the membership of KDE e.V.), which shall +act as a proxy defined in Section 6 of version 3 of the license. + +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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library. If not, see . +*/ + +#ifndef FAKE_ACCESS_POINT_H +#define FAKE_ACCESS_POINT_H + +#include + +#include +#include + +#include + +class KDE_EXPORT FakeAccessPoint : public Solid::Control::Ifaces::AccessPoint +{ +Q_OBJECT +Q_INTERFACES(Solid::Control::Ifaces::AccessPoint) +public: + FakeAccessPoint(const QMap & propsMap, QObject * parent = 0 ); + ~FakeAccessPoint(); + QString uni() const; + Solid::Control::AccessPoint::Capabilities capabilities() const; + Solid::Control::AccessPoint::WpaFlags wpaFlags() const; + Solid::Control::AccessPoint::WpaFlags rsnFlags() const; + QString ssid() const; + uint frequency() const; + QString hardwareAddress() const; + uint maxBitRate() const; + Solid::Control::WirelessNetworkInterface::OperationMode mode() const; + int signalStrength() const; +signals: + void ssidChanged(const QString &); + void frequencyChanged(uint); + void signalStrengthChanged(int strength); + void bitRateChanged(int bitrate); + void wpaFlagsChanged(Solid::Control::AccessPoint::WpaFlags flags); + void rsnFlagsChanged(Solid::Control::AccessPoint::WpaFlags flags); +private: + Solid::Control::AccessPoint::WpaFlags wpaPropsToFlags( const QString & property ) const; + QMap mPropertyMap; + QString mUni; + +}; + +#endif diff --git a/solid/control/backends/fakenet/fakenetworking.xml b/solid/control/backends/fakenet/fakenetworking.xml new file mode 100644 index 000000000..249cfb0b0 --- /dev/null +++ b/solid/control/backends/fakenet/fakenetworking.xml @@ -0,0 +1,97 @@ + + true + true + false + + + eth0 + ipw3945 + true + ieee80211 + 83886080 + 932741824 + true + manageable,carrierdetect + + 193.1.234.22 + 193.1.234.0 + 193.1.234.255 + 193.1.214.50,193.1.214.55 + + wep,wpa,psk,wep40,wep104,tkip + + 00:0D:65:48:6C:06 + privacy + pairwep104,pairtkip,keypsk + + 11 + aKademy + 56623104 + master + 45 + + + 00:0D:65:48:6C:12 + privacy + pairwep104,pairtkip,keypsk + + 11 + aKademy + 56623104 + master + 72 + + + + 00:12:01:B5:21:E0 + privacy + pairwep104 + + 7 + aKademy + 56623104 + master + 12 + + + 00:0D:65:48:7A:2E + 60 + 11534336 + 9 + + master + Kennedy's + + + 00:0D:65:48:6B:B8 + 30 + 56623104 + 5 + privacy + pairwep104 + master + FOSDEM-H2218 + + + + + eth1 + e1000 + 00:16:D3:31:32:21 + true + ieee8023 + connected + 1073741824 + 932741824 + true + manageable,carrierdetect + + + 193.1.233.16 + 193.1.233.0 + 193.1.233.255 + 193.1.219.90,193.1.219.94 + + + + diff --git a/solid/control/backends/fakenet/fakenetworkinterface.cpp b/solid/control/backends/fakenet/fakenetworkinterface.cpp new file mode 100644 index 000000000..31ed48d65 --- /dev/null +++ b/solid/control/backends/fakenet/fakenetworkinterface.cpp @@ -0,0 +1,114 @@ +/* This file is part of the KDE project + Copyright (C) 2006,2008 Will Stephenson + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#include + +#include "fakenetworkinterface.h" + +#include + +FakeNetworkInterface::FakeNetworkInterface(const QMap & propertyMap, QObject * parent) +: QObject(parent), mPropertyMap(propertyMap) +{ +} + +FakeNetworkInterface::~FakeNetworkInterface() +{ +} + + +QString FakeNetworkInterface::uni() const +{ + return mPropertyMap["uni"].toString(); +} + + +QString FakeNetworkInterface::interfaceName() const +{ + return mPropertyMap["interface"].toString(); +} + +QString FakeNetworkInterface::driver() const +{ + return mPropertyMap["driver"].toString(); +} +bool FakeNetworkInterface::isActive() const +{ + return !mActiveConnection.isEmpty(); +} + +Solid::Control::NetworkInterface::ConnectionState FakeNetworkInterface::connectionState() const +{ + QString stateString = mPropertyMap["state"].toString(); + + if (stateString == "unmanaged") + return Solid::Control::NetworkInterface::Unmanaged; + else if (stateString == "unavailable") + return Solid::Control::NetworkInterface::Unavailable; + else if (stateString == "disconnected") + return Solid::Control::NetworkInterface::Disconnected; + else if (stateString == "preparing") + return Solid::Control::NetworkInterface::Preparing; + else if (stateString == "configuring") + return Solid::Control::NetworkInterface::Configuring; + else if (stateString == "needauth") + return Solid::Control::NetworkInterface::NeedAuth; + else if (stateString == "ipconfig") + return Solid::Control::NetworkInterface::IPConfig; + else if (stateString == "activated") + return Solid::Control::NetworkInterface::Activated; + else if (stateString == "failed") + return Solid::Control::NetworkInterface::Failed; + else + return Solid::Control::NetworkInterface::UnknownState; +} + +int FakeNetworkInterface::designSpeed() const +{ + return mPropertyMap["speed"].toInt(); +} + +Solid::Control::NetworkInterface::Capabilities FakeNetworkInterface::capabilities() const +{ + QStringList capStrings = mPropertyMap["capabilities"].toString().simplified().split(','); + + Solid::Control::NetworkInterface::Capabilities caps = 0; + if (capStrings.contains("manageable")) + caps |= Solid::Control::NetworkInterface::IsManageable; + if (capStrings.contains("carrierdetect")) + caps |= Solid::Control::NetworkInterface::SupportsCarrierDetect; + return caps; +} + +void FakeNetworkInterface::activate(const QString & connectionUni, const QString &) +{ + mActiveConnection = connectionUni; +} + +void FakeNetworkInterface::deactivate() +{ + mActiveConnection = ""; +} + + +Solid::Control::IPv4Config FakeNetworkInterface::ipV4Config() const +{ + return Solid::Control::IPv4Config(); +} + diff --git a/solid/control/backends/fakenet/fakenetworkinterface.h b/solid/control/backends/fakenet/fakenetworkinterface.h new file mode 100644 index 000000000..d0e7ccc49 --- /dev/null +++ b/solid/control/backends/fakenet/fakenetworkinterface.h @@ -0,0 +1,65 @@ +/* This file is part of the KDE project + Copyright (C) 2006,2008 Will Stephenson + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#ifndef FAKE_NETWORK_INTERFACE_H +#define FAKE_NETWORK_INTERFACE_H + +#include +#include + +#include + +#include +#include + +using namespace Solid::Control::Ifaces; + +class KDE_EXPORT FakeNetworkInterface : public QObject, virtual public Solid::Control::Ifaces::NetworkInterface +{ + friend class FakeNetworkManager; + Q_OBJECT + Q_INTERFACES(Solid::Control::Ifaces::NetworkInterface) +public: + FakeNetworkInterface(const QMap & propertyMap, + QObject *parent = 0); + virtual ~FakeNetworkInterface(); + QString uni() const; + QString interfaceName() const; + QString driver() const; + bool isActive() const; + Solid::Control::IPv4Config ipV4Config() const; + Solid::Control::NetworkInterface::ConnectionState connectionState() const; + int designSpeed() const; + Solid::Control::NetworkInterface::Capabilities capabilities() const; + void activate(const QString & connectionUni, const QString & extra_connection_parameter = QString() ); + void deactivate(); + Q_SIGNALS: + void ipDetailsChanged(); + void activeChanged(bool); + void linkUpChanged(bool); + void connectionStateChanged(int /*NetworkStatus::ConnectionState */); + + protected: + /* These methods are operations that are carried out by the manager + In a real backend they would be events coming up from the network layer */ + QString mActiveConnection; + QMap mPropertyMap; +}; + +#endif diff --git a/solid/control/backends/fakenet/fakenetworkmanager.cpp b/solid/control/backends/fakenet/fakenetworkmanager.cpp new file mode 100644 index 000000000..a5f548158 --- /dev/null +++ b/solid/control/backends/fakenet/fakenetworkmanager.cpp @@ -0,0 +1,285 @@ +/* This file is part of the KDE project + Copyright (C) 2006,2008 Will Stephenson + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ +#include "fakenetworkmanager.h" + +#include +#include +#include + +#include +#include + +#include "fakeaccesspoint.h" +#include "fakewirednetworkinterface.h" +#include "fakewirelessnetworkinterface.h" + +FakeNetworkManager::FakeNetworkManager(QObject * parent, const QStringList &) : Solid::Control::Ifaces::NetworkManager(parent) +{ + mUserNetworkingEnabled = true; + mUserWirelessEnabled = true; + mRfKillEnabled = false; + mXmlFile = KStandardDirs::locate("data", "solidfakebackend/fakenetworking.xml"); + +// QDBusConnection::sessionBus().registerObject("/org/kde/solid/fake", this, QDBusConnection::ExportNonScriptableSlots); + + parseNetworkingFile(); +} + +FakeNetworkManager::FakeNetworkManager(QObject * parent, const QStringList &, const QString &xmlFile) : Solid::Control::Ifaces::NetworkManager(parent) +{ + mUserNetworkingEnabled = true; + mUserWirelessEnabled = true; + + mXmlFile = xmlFile; + if (mXmlFile.isEmpty()) + { + kDebug() << "Falling back to installed networking xml"; + mXmlFile = KStandardDirs::locate("data", "solidfakebackend/fakenetworking.xml"); + } + parseNetworkingFile(); +} + +FakeNetworkManager::~FakeNetworkManager() +{ +} + +Solid::Networking::Status FakeNetworkManager::status() const +{ + return Solid::Networking::Unknown; +} + +QStringList FakeNetworkManager::networkInterfaces() const +{ + return mNetworkInterfaces.keys(); +} + +QStringList FakeNetworkManager::activeNetworkInterfaces() const +{ + QStringList activeDevices; + QMapIterator it(mNetworkInterfaces); + while (it.hasNext()) + { + it.next(); + FakeNetworkInterface * netDevice = it.value(); + if (netDevice->isActive()) + activeDevices.append(netDevice->uni()); + } + return activeDevices; +} + +QObject * FakeNetworkManager::createNetworkInterface(const QString & undi) +{ + if (mNetworkInterfaces.contains(undi)) + return mNetworkInterfaces[undi]; + else + return 0; +} + +bool FakeNetworkManager::isWirelessEnabled() const +{ + return mUserWirelessEnabled; +} + +bool FakeNetworkManager::isNetworkingEnabled() const +{ + QMapIterator it(mNetworkInterfaces); + while (it.hasNext()) + { + it.next(); + FakeNetworkInterface * netDevice = it.value(); + if (netDevice->isActive()) + return true; + } + return false; +} + +bool FakeNetworkManager::isWirelessHardwareEnabled() const +{ + return mRfKillEnabled; +} + +void FakeNetworkManager::setWirelessEnabled(bool enabled) +{ + mUserWirelessEnabled = enabled; +} + +void FakeNetworkManager::setNetworkingEnabled(bool enabled) +{ + QMapIterator it(mNetworkInterfaces); + while (it.hasNext()) + { + it.next(); + FakeNetworkInterface * netDevice = it.value(); + // if ((netDevice->type() == Solid::Control::NetworkInterface::Ieee80211 && mUserWirelessEnabled) + // || netDevice->type() == Solid::Control::NetworkInterface::Ieee8023) + // netDevice->setActive(enabled); + } + mUserNetworkingEnabled = enabled; +} + +void FakeNetworkManager::parseNetworkingFile() +{ + QFile machineFile(mXmlFile); + if (!machineFile.open(QIODevice::ReadOnly)) + { + kDebug() << "Error while opening " << mXmlFile; + return; + } + + QDomDocument fakeDocument; + if (!fakeDocument.setContent(&machineFile)) + { + kDebug() << "Error while creating the QDomDocument."; + machineFile.close(); + return; + } + machineFile.close(); + + kDebug() << "Parsing fake computer XML: " << mXmlFile; + QDomElement mainElement = fakeDocument.documentElement(); + QDomNode node = mainElement.firstChild(); + while (!node.isNull()) + { + QDomElement tempElement = node.toElement(); + if (!tempElement.isNull() && tempElement.tagName() == QLatin1String("device")) + { + FakeNetworkInterface *tempDevice = parseDeviceElement(tempElement); + if(tempDevice) + { + mNetworkInterfaces.insert(tempDevice->uni(), tempDevice); +// Use the DeviceManager for now, the udi/uni should +// emit deviceAdded(tempDevice->uni()); + } + } else if (tempElement.tagName() == QLatin1String("property")) { + QString propertyKey = tempElement.attribute("key"); + QVariant propertyValue = QVariant(tempElement.text()); + if ( propertyKey== QLatin1String("networking")) { + mUserNetworkingEnabled = propertyValue.toBool(); + } else if ( propertyKey== QLatin1String("wireless")) { + mUserWirelessEnabled = propertyValue.toBool(); + } else if ( propertyKey== QLatin1String("rfkill")) { + mRfKillEnabled = propertyValue.toBool(); + } + } + node = node.nextSibling(); + } +} + +FakeNetworkInterface *FakeNetworkManager::parseDeviceElement(const QDomElement &deviceElement) +{ + FakeNetworkInterface *device = 0; + QMap propertyMap; + QString uni = deviceElement.attribute("uni"); + propertyMap.insert("uni", uni); + kDebug() << "Listing device: " << uni; + propertyMap.insert("uni", QVariant(uni)); + QList< FakeAccessPoint * > networks; + bool wireless = false; + QDomNode childNode = deviceElement.firstChild(); + while (!childNode.isNull()) + { + QDomElement childElement = childNode.toElement(); + //kDebug() << "found child=" << childElement.tagName(); + if (!childElement.isNull() && childElement.tagName() == QLatin1String("property")) + { + QString propertyKey; + QVariant propertyValue; + + propertyKey = childElement.attribute("key"); + propertyValue = QVariant(childElement.text()); + if ( propertyValue == "ieee80211" ) { + wireless = true; + } + //kDebug() << "Got property key=" << propertyKey << ", value=" << propertyValue.toString(); + propertyMap.insert(propertyKey, propertyValue); + } + else if (!childElement.isNull() && childElement.tagName() == QLatin1String("accesspoint")) + { + QString uni = childElement.attribute("uni"); + kDebug() << "Listing properties: " << uni; + FakeAccessPoint * wifi = new FakeAccessPoint(parseAPElement(childElement), this); + networks.append(wifi); + } + childNode = childNode.nextSibling(); + } + //kDebug() << "Done listing. "; + +/* if (!propertyMap.isEmpty()) + { */ + kDebug() << "Creating FakeNetworkDevice for " << uni; + if (wireless) { + FakeWirelessNetworkInterface * wifi = new FakeWirelessNetworkInterface(propertyMap); + foreach( FakeAccessPoint * net, networks) + { + kDebug() << "Injecting " << net->uni(); + wifi->injectAccessPoint(net); + } + device = wifi; + } else { + device = new FakeWiredNetworkInterface(propertyMap); + } + + +// } + + return device; +} + +QMap FakeNetworkManager::parseAPElement(const QDomElement &deviceElement) +{ + QMap propertyMap; + + QDomNode propertyNode = deviceElement.firstChild(); + while (!propertyNode.isNull()) + { + QDomElement propertyElement = propertyNode.toElement(); + if (!propertyElement.isNull() && propertyElement.tagName() == QLatin1String("property")) + { + QString propertyKey; + QVariant propertyValue; + + propertyKey = propertyElement.attribute("key"); + propertyValue = QVariant(propertyElement.text()); + //kDebug() << "Got property key=" << propertyKey << ", value=" << propertyValue.toString(); + propertyMap.insert(propertyKey, propertyValue); + } + + propertyNode = propertyNode.nextSibling(); + } + return propertyMap; +} + +void FakeNetworkManager::activateConnection(const QString & interfaceUni, const QString & connectionUni, const QVariantMap & connectionParameters) +{ + mActiveConnections.append(connectionUni); + QTimer::singleShot(0, this, SIGNAL(activeConnectionsChanged())); +} + +void FakeNetworkManager::deactivateConnection(const QString & activeConnection) +{ + mActiveConnections.removeAll(activeConnection); +} + +QStringList FakeNetworkManager::activeConnections() const +{ + return mActiveConnections; +} + +#include "fakenetworkmanager.moc" + diff --git a/solid/control/backends/fakenet/fakenetworkmanager.h b/solid/control/backends/fakenet/fakenetworkmanager.h new file mode 100644 index 000000000..163768c02 --- /dev/null +++ b/solid/control/backends/fakenet/fakenetworkmanager.h @@ -0,0 +1,79 @@ +/* This file is part of the KDE project + Copyright (C) 2006,2008 Will Stephenson + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#ifndef FAKE_NETWORK_MANAGER_H +#define FAKE_NETWORK_MANAGER_H + +#include +#include + +#include + +#include + +#include "fakenetworkinterface.h" + + +class FakeAuthenticationValidator; +class QDomElement; +//class FakeNetworkInterface; + +namespace Solid { + class Authentication; +} + +class KDE_EXPORT FakeNetworkManager : public Solid::Control::Ifaces::NetworkManager +{ +Q_OBJECT + public: + FakeNetworkManager(QObject * parent, const QStringList & args); + FakeNetworkManager(QObject * parent, const QStringList & args, const QString & xmlFile); + virtual ~FakeNetworkManager(); + Solid::Networking::Status status() const; + QStringList networkInterfaces() const; + QStringList activeNetworkInterfaces() const; + QObject * createNetworkInterface(const QString &); + + bool isNetworkingEnabled() const; + bool isWirelessEnabled() const; + bool isWirelessHardwareEnabled() const; + + void activateConnection(const QString & interfaceUni, const QString & connectionUni, const QVariantMap & connectionParameters); + + void deactivateConnection(const QString & activeConnection); + QStringList activeConnections() const; + + public Q_SLOTS: + void setWirelessEnabled(bool); + void setNetworkingEnabled(bool); + + private: + void parseNetworkingFile(); + FakeNetworkInterface *parseDeviceElement(const QDomElement &deviceElement); + QMap parseAPElement(const QDomElement &deviceElement); + + bool mUserNetworkingEnabled; + bool mUserWirelessEnabled; + bool mRfKillEnabled; + QMap mNetworkInterfaces; + QStringList mActiveConnections; + QString mXmlFile; +}; + +#endif diff --git a/solid/control/backends/fakenet/fakewirednetworkinterface.cpp b/solid/control/backends/fakenet/fakewirednetworkinterface.cpp new file mode 100644 index 000000000..cb4ed20a3 --- /dev/null +++ b/solid/control/backends/fakenet/fakewirednetworkinterface.cpp @@ -0,0 +1,50 @@ +/* +Copyright 2008 Will Stephenson + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) version 3, or any +later version accepted by the membership of KDE e.V. (or its +successor approved by the membership of KDE e.V.), which shall +act as a proxy defined in Section 6 of version 3 of the license. + +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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library. If not, see . +*/ + +#include + +#include "fakewirednetworkinterface.h" + +FakeWiredNetworkInterface::FakeWiredNetworkInterface(const QMap & propertyMap, QObject * parent) +: FakeNetworkInterface(propertyMap, parent) +{ +} + +FakeWiredNetworkInterface::~FakeWiredNetworkInterface() +{ +} + +QString FakeWiredNetworkInterface::hardwareAddress() const +{ + return mPropertyMap["hwaddress"].toString(); + +} + +bool FakeWiredNetworkInterface::carrier() const +{ + return mPropertyMap["carrier"].toBool(); +} + +int FakeWiredNetworkInterface::bitRate() const +{ + return mPropertyMap["bitrate"].toInt(); +} + +#include "fakewirednetworkinterface.moc" diff --git a/solid/control/backends/fakenet/fakewirednetworkinterface.h b/solid/control/backends/fakenet/fakewirednetworkinterface.h new file mode 100644 index 000000000..d49f20afb --- /dev/null +++ b/solid/control/backends/fakenet/fakewirednetworkinterface.h @@ -0,0 +1,51 @@ +/* +Copyright 2008 Will Stephenson + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) version 3, or any +later version accepted by the membership of KDE e.V. (or its +successor approved by the membership of KDE e.V.), which shall +act as a proxy defined in Section 6 of version 3 of the license. + +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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library. If not, see . +*/ + +#ifndef FAKE_WIRED_NETWORK_INTERFACE_H +#define FAKE_WIRED_NETWORK_INTERFACE_H + +#include +#include + +#include + +#include + +#include "fakenetworkinterface.h" + +using namespace Solid::Control::Ifaces; + +class KDE_EXPORT FakeWiredNetworkInterface : public FakeNetworkInterface, virtual public Solid::Control::Ifaces::WiredNetworkInterface +{ +Q_OBJECT +Q_INTERFACES(Solid::Control::Ifaces::WiredNetworkInterface) +public: + FakeWiredNetworkInterface(const QMap & propertyMap, QObject * parent = 0); + ~FakeWiredNetworkInterface(); + QString hardwareAddress() const; + int bitRate() const; + bool carrier() const; +signals: + void bitRateChanged(int bitrate); + void carrierChanged(bool plugged); +}; + +#endif + diff --git a/solid/control/backends/fakenet/fakewirelessnetworkinterface.cpp b/solid/control/backends/fakenet/fakewirelessnetworkinterface.cpp new file mode 100644 index 000000000..5e0192b8b --- /dev/null +++ b/solid/control/backends/fakenet/fakewirelessnetworkinterface.cpp @@ -0,0 +1,77 @@ +/* +Copyright 2008 Will Stephenson + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) version 3, or any +later version accepted by the membership of KDE e.V. (or its +successor approved by the membership of KDE e.V.), which shall +act as a proxy defined in Section 6 of version 3 of the license. + +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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library. If not, see . +*/ + +#include + +#include "fakeaccesspoint.h" +#include "fakewirelessnetworkinterface.h" + +FakeWirelessNetworkInterface::FakeWirelessNetworkInterface(const QMap & propertyMap, QObject * parent) +: FakeNetworkInterface(propertyMap, parent) +{ +} + +FakeWirelessNetworkInterface::~FakeWirelessNetworkInterface() +{ +} + +MacAddressList FakeWirelessNetworkInterface::accessPoints() const +{ + return mAccessPoints.keys(); +} + +QString FakeWirelessNetworkInterface::activeAccessPoint() const +{ + return mPropertyMap["activeaccesspoint"].toString(); +} + +QString FakeWirelessNetworkInterface::hardwareAddress() const +{ + return mPropertyMap["hwaddress"].toString(); + +} + +Solid::Control::WirelessNetworkInterface::OperationMode FakeWirelessNetworkInterface::mode() const +{ + return (Solid::Control::WirelessNetworkInterface::OperationMode)mPropertyMap["operationmode"].toUInt(); +} + + +int FakeWirelessNetworkInterface::bitRate() const +{ + return mPropertyMap["bitrate"].toInt(); +} + +Solid::Control::WirelessNetworkInterface::Capabilities FakeWirelessNetworkInterface::wirelessCapabilities() const +{ + return (Solid::Control::WirelessNetworkInterface::Capabilities)mPropertyMap["wirelesscaps"].toUInt(); +} + +QObject * FakeWirelessNetworkInterface::createAccessPoint(const QString & uni) +{ + return 0; +} + +void FakeWirelessNetworkInterface::injectAccessPoint( FakeAccessPoint * ap ) +{ + mAccessPoints.insert(ap->uni(), ap ); +} + +#include "fakewirelessnetworkinterface.moc" diff --git a/solid/control/backends/fakenet/fakewirelessnetworkinterface.h b/solid/control/backends/fakenet/fakewirelessnetworkinterface.h new file mode 100644 index 000000000..79c309437 --- /dev/null +++ b/solid/control/backends/fakenet/fakewirelessnetworkinterface.h @@ -0,0 +1,62 @@ +/* +Copyright 2008 Will Stephenson + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) version 3, or any +later version accepted by the membership of KDE e.V. (or its +successor approved by the membership of KDE e.V.), which shall +act as a proxy defined in Section 6 of version 3 of the license. + +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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library. If not, see . +*/ + +#ifndef FAKE_WIRELESS_NETWORK_INTERFACE_H +#define FAKE_WIRELESS_NETWORK_INTERFACE_H + +#include "fakenetworkinterface.h" +#include +#include +#include +#include + +class FakeAccessPoint; +#include + +class KDE_EXPORT FakeWirelessNetworkInterface : public FakeNetworkInterface, virtual public Solid::Control::Ifaces::WirelessNetworkInterface +{ +Q_OBJECT +Q_INTERFACES(Solid::Control::Ifaces::WirelessNetworkInterface) +friend class FakeNetworkManager; +public: + FakeWirelessNetworkInterface(const QMap & propertyMap, QObject * parent = 0); + ~FakeWirelessNetworkInterface(); + MacAddressList accessPoints() const; + QString activeAccessPoint() const; + QString hardwareAddress() const; + Solid::Control::WirelessNetworkInterface::OperationMode mode() const; + int bitRate() const; + Solid::Control::WirelessNetworkInterface::Capabilities wirelessCapabilities() const; + QObject * createAccessPoint(const QString & uni); +signals: + void bitRateChanged(int bitrate); + void activeAccessPointChanged(const QString &); + void modeChanged(Solid::Control::WirelessNetworkInterface::OperationMode); + void accessPointAppeared(const QString &); + void accessPointDisappeared(const QString &); +protected: + void injectAccessPoint( FakeAccessPoint * ap ); +private: + QMap mAccessPoints; + +}; + +#endif + diff --git a/solid/control/backends/fakenet/module.cpp b/solid/control/backends/fakenet/module.cpp new file mode 100644 index 000000000..3eb96ed3d --- /dev/null +++ b/solid/control/backends/fakenet/module.cpp @@ -0,0 +1,27 @@ +/* This file is part of the KDE project + Copyright (C) 2006 Will Stephenson + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#include "fakenetworkmanager.h" + +// KDE includes +#include + +typedef KGenericFactory FakeNetBackendFactory; +K_EXPORT_COMPONENT_FACTORY(solid_fake_netmgmt, FakeNetBackendFactory("fakenetbackend")) + diff --git a/solid/control/backends/fakenet/solid_fakenet.desktop b/solid/control/backends/fakenet/solid_fakenet.desktop new file mode 100644 index 000000000..ef08ce0c4 --- /dev/null +++ b/solid/control/backends/fakenet/solid_fakenet.desktop @@ -0,0 +1,126 @@ +[Desktop Entry] +Type=Service +X-KDE-ServiceTypes=SolidNetworkManager +X-KDE-Library=solid_fakenet +InitialPreference=10 +Icon=network-workgroup +Name=Fake Net +Name[af]=Netwerk-nabootsing +Name[be]=Падробка пад сетку +Name[be@latin]=Udavanaja sietka +Name[ca]=Xarxa falsa +Name[csb]=Falszëwô séc +Name[da]=Falsk net +Name[de]=Netzwerk (Dummy) +Name[el]=Πλαστό δίκτυο +Name[eo]=Ŝajnigita reto +Name[es]=Red falsa +Name[et]=Liba-võrk +Name[eu]=Sare faltsua +Name[fa]=شبکۀ جعلی +Name[fi]=Väärä verkko +Name[fr]=Réseau factice +Name[fy]=Ferfalske net +Name[ga]=Líonra Bréige +Name[gl]=Rede falsa +Name[gu]=ખોટું નેટ +Name[he]=רשת מזוייפת +Name[hi]=नक़ली नेट +Name[hu]=Hálózat (imitáció) +Name[is]=Falskt net +Name[ja]=疑似ネット +Name[kk]=Жалған Желі +Name[km]=សំណាញ់​ក្លែងក្លាយ​ +Name[kn]=ನಕಲಿ ಜಾಲ +Name[ko]=가짜 네트워크 +Name[lt]=Netikras tinklas +Name[lv]=Neīsts tīkls +Name[mr]=बनावटी नेट +Name[nb]=Falsk nettverk +Name[nds]=Nettwark (Platzholler) +Name[ne]=नक्कली नेट +Name[nl]=Nep net +Name[nn]=Falskt nettverk +Name[pa]=ਫ਼ਰਜੀ ਨੈੱਟ +Name[pl]=Nieprawdziwa sieć +Name[pt]=Rede Falsa +Name[pt_BR]=Rede Falsa +Name[ro]=Rețea falsă +Name[ru]=Фальшивая сеть +Name[se]=Mahkáš-fierpmádat +Name[sl]=Lažno omrežje +Name[sr]=Лажна мрежа +Name[sr@latin]=Lažna mreža +Name[sv]=Testnät +Name[te]=నకిలీ నెట్ +Name[tg]=Шабакаи Fake +Name[th]=เครือข่ายเทียม +Name[tr]=Sahte Ağ +Name[uk]=Фальшива мережа +Name[vi]=Mạng giả +Name[wa]=Fåsse toele +Name[x-test]=xxFake Netxx +Name[zh_CN]=虚假网络 +Name[zh_TW]=Fake 網路 +Comment=Fake Network Management +Comment[af]=Netwerk-nabootsing beheer +Comment[be]=Кіраванне падробная сеткай +Comment[be@latin]=Kiravańnie udavanaj sietkaj +Comment[bg]=Фалшива мрежа +Comment[ca]=Gestió de xarxa falsa +Comment[csb]=Sprôwianié falszëwą sécą +Comment[da]=Håndtering af falsk netværk +Comment[de]=Netzwerkverwaltung (Dummy) +Comment[el]=Διαχειριστής πλαστού δικτύου +Comment[eo]=Administrilo de ŝajnigita reto +Comment[es]=Gestión de red falsa +Comment[et]=Liba-võrgu haldur +Comment[eu]=Sare faltsu kudeaketa +Comment[fa]=مدیریت شبکۀ جعلی +Comment[fi]=Väärän verkon hallinta +Comment[fr]=Gestionnaire de réseau factice +Comment[fy]=Ferfalske netwurkbehear +Comment[ga]=Bainisteoireacht Líonra Bréige +Comment[gl]=Xestión de rede falsa +Comment[gu]=ખોટું નેટવર્ક વ્યવસ્થાપક +Comment[he]=ניהול רשת מזוייף +Comment[hi]=नक़ली नेटवर्क प्रबंधन +Comment[hr]=Mrežno upravljanje +Comment[hu]=Hálózatkezelés (imitáció) +Comment[is]=Fölsk netstýring +Comment[it]=Gestione di una falsa rete +Comment[ja]=疑似ネット管理 +Comment[kk]=Жалған Желіні басқару +Comment[km]=ការ​គ្រប់គ្រង​បណ្តាញ​ក្លែងក្លាយ​ +Comment[kn]=ನಕಲಿ ಜಾಲ ವ್ಯವಸ್ಥಾಪನೆ +Comment[ko]=가짜 네트워크 관리 +Comment[lt]=Netikro tinklo tvarkymas +Comment[lv]=Neīsta tīkla pārvaldnieks +Comment[ml]=ഫെയിക് നെറ്റ്‌വര്‍ക്ക് മാനേജ്മെന്റ് +Comment[mr]=बनावटी संजाळ व्यवस्थापन +Comment[nb]=Falsk nettverksstyring +Comment[nds]=Nettwark-Pleger (Platzholler) +Comment[ne]=नक्कली सञ्जाल व्यवस्थापन +Comment[nl]=Nep netwerkbeheer +Comment[nn]=Falskt nettverk-handtering +Comment[pa]=ਫ਼ਰਜ਼ੀ ਨੈੱਟਵਰਕ ਮੈਨਿਜਮੈਂਟ +Comment[pl]=Nieprawdziwe zarządzanie siecią +Comment[pt]=Gestão da Rede Falsa +Comment[pt_BR]=Gerenciamento de Rede Falsa +Comment[ro]=Management de rețea fals +Comment[ru]=Управление фальшивой сетью +Comment[se]=Mahkáš-fierpmádat-gieđahallan +Comment[sl]=Upravljanje z lažnimi omrežji +Comment[sr]=Управљање лажном мрежом +Comment[sr@latin]=Upravljanje lažnom mrežom +Comment[sv]=Hantering av testnätverk +Comment[te]=నకిలీ నెట్వర్‍క్ నిర్వహణ +Comment[tg]=Идоракунии шабакаи Fake +Comment[th]=การจัดการเครือข่ายเทียม +Comment[tr]=Sahte Ağ Yönetimi +Comment[uk]=Керування фальшивою мережею +Comment[vi]=Quản lý mạng giả +Comment[wa]=Fås manaedjmint d' rantoele +Comment[x-test]=xxFake Network Managementxx +Comment[zh_CN]=虚假网络管理 +Comment[zh_TW]=Fake 網路管理 diff --git a/solid/control/backends/fakenet/tests/CMakeLists.txt b/solid/control/backends/fakenet/tests/CMakeLists.txt new file mode 100644 index 000000000..e4bcf79ac --- /dev/null +++ b/solid/control/backends/fakenet/tests/CMakeLists.txt @@ -0,0 +1,18 @@ +set( EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR} ) + +include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/.. ) + +########### next target ############### + +set(fakenetworktest_SRCS fakenetworktest.cpp ) + + +kde4_add_unit_test(fakenetworktest ${fakenetworktest_SRCS}) + +target_link_libraries(fakenetworktest solid_fakenet_static solidcontrolifaces ${KDE4_KDECORE_LIBS} ${QT_QTTEST_LIBRARY} ) +add_definitions(-DTEST_DATA="\\"${CMAKE_CURRENT_SOURCE_DIR}/../fakenetworking.xml\\"") + +########### install files ############### + + + diff --git a/solid/control/backends/fakenet/tests/fakenetworktest.cpp b/solid/control/backends/fakenet/tests/fakenetworktest.cpp new file mode 100644 index 000000000..9e161378b --- /dev/null +++ b/solid/control/backends/fakenet/tests/fakenetworktest.cpp @@ -0,0 +1,38 @@ +/* This file is part of the KDE project + Copyright (C) 2006 Will Stephenson + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +// KDE-QTestLib include +#include + +#include "fakenetworkmanager.h" + +#include "fakenetworktest.h" + +QTEST_KDEMAIN_CORE(FakeNetworking_Test) + +void FakeNetworking_Test::testFakeNetworking() +{ + FakeNetworkManager *fnm = new FakeNetworkManager(0, QStringList(), TEST_DATA); + QVERIFY(!fnm->networkInterfaces().isEmpty()); + QVERIFY(fnm->createNetworkInterface("/org/kde/solid/fakenet/eth0") != 0); + QVERIFY(fnm->createNetworkInterface("/org/kde/wobbly/jellynet/eth0") == 0); + delete fnm; +} + +#include "fakenetworktest.moc" diff --git a/solid/control/backends/fakenet/tests/fakenetworktest.h b/solid/control/backends/fakenet/tests/fakenetworktest.h new file mode 100644 index 000000000..cd47f2623 --- /dev/null +++ b/solid/control/backends/fakenet/tests/fakenetworktest.h @@ -0,0 +1,32 @@ +/* This file is part of the KDE project + Copyright (C) 2006 Will Stephenson + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#ifndef FAKEBACKENDTEST_H +#define FAKEBACKENDTEST_H + +#include + +class FakeNetworking_Test : public QObject +{ + Q_OBJECT +private slots: + void testFakeNetworking(); +}; + +#endif diff --git a/solid/control/bluetoothinputdevice.cpp b/solid/control/bluetoothinputdevice.cpp new file mode 100644 index 000000000..b25a2fda9 --- /dev/null +++ b/solid/control/bluetoothinputdevice.cpp @@ -0,0 +1,99 @@ +/* This file is part of the KDE project + Copyright (C) 2006 Will Stephenson + Copyright (C) 2007 Daniel Gollub + + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#include + +#include "ifaces/bluetoothinputdevice.h" + +#include "frontendobject_p.h" + +#include "soliddefs_p.h" + +#include "bluetoothinputdevice.h" + +namespace Solid +{ +namespace Control +{ + class BluetoothInputDevicePrivate : public FrontendObjectPrivate + { + public: + BluetoothInputDevicePrivate(QObject *parent) + : FrontendObjectPrivate(parent) { } + + void setBackendObject(QObject *object); + }; +} +} + +Solid::Control::BluetoothInputDevice::BluetoothInputDevice(QObject *backendObject) + : QObject(), d(new BluetoothInputDevicePrivate(this)) +{ + d->setBackendObject(backendObject); +} + +Solid::Control::BluetoothInputDevice::BluetoothInputDevice(const BluetoothInputDevice &device) + : QObject(), d(new BluetoothInputDevicePrivate(this)) +{ + d->setBackendObject(device.d->backendObject()); +} + +Solid::Control::BluetoothInputDevice::~BluetoothInputDevice() +{} + +Solid::Control::BluetoothInputDevice &Solid::Control::BluetoothInputDevice::operator=(const Solid::Control::BluetoothInputDevice & dev) +{ + d->setBackendObject(dev.d->backendObject()); + + return *this; +} + +QString Solid::Control::BluetoothInputDevice::ubi() const +{ + return_SOLID_CALL(Ifaces::BluetoothInputDevice *, d->backendObject(), QString(), ubi()); +} + +QMap Solid::Control::BluetoothInputDevice::getProperties() const +{ + return_SOLID_CALL(Ifaces::BluetoothInputDevice *, d->backendObject(), (QMap< QString,QVariant >()), getProperties()); +} + +void Solid::Control::BluetoothInputDevice::connect() +{ + SOLID_CALL(Ifaces::BluetoothInputDevice *, d->backendObject(), connect()); +} + +void Solid::Control::BluetoothInputDevice::disconnect() +{ + SOLID_CALL(Ifaces::BluetoothInputDevice *, d->backendObject(), disconnect()); +} + +void Solid::Control::BluetoothInputDevicePrivate::setBackendObject(QObject *object) +{ + FrontendObjectPrivate::setBackendObject(object); + + if (object) { + QObject::connect(object, SIGNAL(propertyChanged(QString,QVariant)), + parent(), SIGNAL(propertyChanged(QString,QVariant))); + } +} + +#include "bluetoothinputdevice.moc" diff --git a/solid/control/bluetoothinputdevice.h b/solid/control/bluetoothinputdevice.h new file mode 100644 index 000000000..a34cfa936 --- /dev/null +++ b/solid/control/bluetoothinputdevice.h @@ -0,0 +1,123 @@ +/* This file is part of the KDE project + Copyright (C) 2007 Will Stephenson + Copyright (C) 2007 Daniel Gollub + Copyright (C) 2008 Tom Patzig + + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#ifndef SOLID_CONTROL_BLUETOOTHINPUTDEVICE_H +#define SOLID_CONTROL_BLUETOOTHINPUTDEVICE_H + +#include +#include +#include + +#include "solid_control_export.h" + +namespace Solid +{ +namespace Control +{ +class BluetoothInputDevicePrivate; + +/** + * Represents a bluetooth remote device as seen by the bluetoothing subsystem. + */ +class SOLIDCONTROL_EXPORT BluetoothInputDevice : public QObject +{ + Q_OBJECT + +public: + /** + * Creates a new BluetoothInputDevice object. + * + * @param backendObject the bluetooth remote device object provided by the backend + */ + BluetoothInputDevice(QObject *backendObject = 0); + + /** + * Constructs a copy of a bluetooth remote device. + * + * @param device the bluetooth remote device to copy + */ + BluetoothInputDevice(const BluetoothInputDevice &device); + + /** + * Destroys the device. + */ + ~BluetoothInputDevice(); + + /** + * Assigns a bluetooth remote device to this bluetooth remote device and returns a reference to it. + * + * @param device the bluetooth remote device to assign + * @return a reference to the bluetooth remote device + */ + BluetoothInputDevice &operator=(const BluetoothInputDevice &device); + + /** + * Retrieves the Universal Network Identifier (UBI) of the BluetoothInputDevice. + * This identifier is ubique for each bluetooth and bluetooth remote device in the system. + * + * @returns the Universal Network Identifier of the current bluetooth remote device + */ + QString ubi() const; + /** + * Retrieve all properties from the input device. + * + * @returns a hash of named properties + */ + QMap getProperties() const; + + + +public Q_SLOTS: + /** + * Connect bluetooth input device. + */ + void connect(); + + /** + * Disconnect bluetooth input device. + */ + void disconnect(); + + +Q_SIGNALS: + /** + * A Property for the input device has changed. + * + * @param name the name of the changed property + * @param value the new value + */ + void propertyChanged(const QString &name, const QVariant &value); + + +private: + Q_PRIVATE_SLOT(d, void _k_destroyed(QObject *)) + + BluetoothInputDevicePrivate * const d; +}; + +} //Control + +} //Solid + +//Q_DECLARE_OPERATORS_FOR_FLAGS(Solid::Control::BluetoothInputDevice::Capabilities) + +#endif diff --git a/solid/control/bluetoothinterface.cpp b/solid/control/bluetoothinterface.cpp new file mode 100644 index 000000000..59326ad3d --- /dev/null +++ b/solid/control/bluetoothinterface.cpp @@ -0,0 +1,474 @@ +/* This file is part of the KDE project + Copyright (C) 2006 Will Stephenson + Copyright (C) 2007 Daniel Gollub + Copyright (C) 2008 Tom Patzig + + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#include +#include +#include +#include + +#include + +#include "ifaces/bluetoothinterface.h" + +#include "frontendobject_p.h" + +#include "soliddefs_p.h" +#include "bluetoothmanager.h" +#include "bluetoothinterface.h" +#include "bluetoothremotedevice.h" + +namespace Solid +{ +namespace Control +{ +class BluetoothInterfacePrivate : public FrontendObjectPrivate +{ +public: + BluetoothInterfacePrivate(QObject *parent) + : FrontendObjectPrivate(parent) { } + + void setBackendObject(QObject *object); + + QPair findRegisteredBluetoothRemoteDevice(const QString &ubi) const; + + mutable QMap > remoteDeviceMap; + mutable BluetoothRemoteDevice invalidDevice; +}; +} +} + +Solid::Control::BluetoothInterface::BluetoothInterface() + : QObject(), d(new BluetoothInterfacePrivate(this)) +{} + +Solid::Control::BluetoothInterface::BluetoothInterface(const QString &ubi) + : QObject(), d(new BluetoothInterfacePrivate(this)) +{ + const BluetoothInterface &device = BluetoothManager::self().findBluetoothInterface(ubi); + d->setBackendObject(device.d->backendObject()); +} + +Solid::Control::BluetoothInterface::BluetoothInterface(QObject *backendObject) + : QObject(), d(new BluetoothInterfacePrivate(this)) +{ + d->setBackendObject(backendObject); +} + +Solid::Control::BluetoothInterface::BluetoothInterface(const BluetoothInterface &device) + : QObject(), d(new BluetoothInterfacePrivate(this)) +{ + d->setBackendObject(device.d->backendObject()); +} + +Solid::Control::BluetoothInterface::~BluetoothInterface() +{ + // Delete all the interfaces, they are now outdated + typedef QPair BluetoothRemoteDeviceIfacePair; + + // Delete all the devices, they are now outdated + foreach (const BluetoothRemoteDeviceIfacePair &pair, d->remoteDeviceMap) { + delete pair.first; + delete pair.second; + } +} + +Solid::Control::BluetoothInterface &Solid::Control::BluetoothInterface::operator=(const Solid::Control::BluetoothInterface & dev) +{ + d->setBackendObject(dev.d->backendObject()); + + return *this; +} + +QString Solid::Control::BluetoothInterface::ubi() const +{ + return_SOLID_CALL(Ifaces::BluetoothInterface *, d->backendObject(), QString(), ubi()); +} + +void Solid::Control::BluetoothInterface::cancelDeviceCreation(const QString &address) const +{ + SOLID_CALL(Ifaces::BluetoothInterface *, d->backendObject(), cancelDeviceCreation(address)); +} + +QString Solid::Control::BluetoothInterface::createPairedDevice(const QString &address,const QString &adapterPath, const QString &capab) const +{ + return_SOLID_CALL(Ifaces::BluetoothInterface *, d->backendObject(), QString(), createPairedDevice(address,adapterPath,capab)); +} + +QMap Solid::Control::BluetoothInterface::getProperties() const +{ + return_SOLID_CALL(Ifaces::BluetoothInterface *, d->backendObject(), (QMap()), getProperties()); +} + +Solid::Control::BluetoothRemoteDeviceList Solid::Control::BluetoothInterface::listDevices() const +{ + Ifaces::BluetoothInterface *backend = qobject_cast(d->backendObject()); + if (backend == 0) + return Solid::Control::BluetoothRemoteDeviceList(); + + QStringList ubis = backend->listDevices(); + + Solid::Control::BluetoothRemoteDeviceList list; + foreach (QString ubi,ubis) { + BluetoothRemoteDevice remoteDevice = findBluetoothRemoteDevice(ubi); + list.append(remoteDevice); + } + return list; +} + +void Solid::Control::BluetoothInterface::registerAgent(const QString &path, const QString &capab) const +{ + SOLID_CALL(Ifaces::BluetoothInterface *, d->backendObject(), registerAgent(path,capab)); +} + +void Solid::Control::BluetoothInterface::releaseSession() const +{ + SOLID_CALL(Ifaces::BluetoothInterface *, d->backendObject(), releaseSession()); +} + +void Solid::Control::BluetoothInterface::requestSession() const +{ + SOLID_CALL(Ifaces::BluetoothInterface *, d->backendObject(), requestSession()); +} + +void Solid::Control::BluetoothInterface::removeDevice(const QString &path) const +{ + SOLID_CALL(Ifaces::BluetoothInterface *, d->backendObject(), removeDevice(path)); +} + +void Solid::Control::BluetoothInterface::setProperty(const QString &property, const QVariant &value) const +{ + SOLID_CALL(Ifaces::BluetoothInterface *, d->backendObject(), setProperty(property,value)); +} + +void Solid::Control::BluetoothInterface::startDiscovery() const +{ + SOLID_CALL(Ifaces::BluetoothInterface *, d->backendObject(), startDiscovery()); +} + +void Solid::Control::BluetoothInterface::stopDiscovery() const +{ + SOLID_CALL(Ifaces::BluetoothInterface *, d->backendObject(), stopDiscovery()); +} + +void Solid::Control::BluetoothInterface::unregisterAgent(const QString &path) const +{ + SOLID_CALL(Ifaces::BluetoothInterface *, d->backendObject(), unregisterAgent(path)); +} + + +Solid::Control::BluetoothRemoteDevice Solid::Control::BluetoothInterface::findBluetoothRemoteDevice(const QString &address) const +{ + Ifaces::BluetoothInterface *backend = qobject_cast(d->backendObject()); + if (backend == 0) + return d->invalidDevice; + + const QString ubi = backend->findDevice(address); + + QPair pair = d->findRegisteredBluetoothRemoteDevice(ubi); + + if (pair.first != 0) { + return *pair.first; + } else { + return d->invalidDevice; + } +} + +Solid::Control::BluetoothRemoteDevice * Solid::Control::BluetoothInterface::createBluetoothRemoteDevice(const QString &address) +{ + Ifaces::BluetoothInterface *backend = qobject_cast(d->backendObject()); + if (backend == 0) + return 0; + + const QString ubi = backend->createDevice(address); + + QPair pair = d->findRegisteredBluetoothRemoteDevice(ubi); + return pair.first; +} + +/* +QString Solid::Control::BluetoothInterface::address() const +{ + return_SOLID_CALL(Ifaces::BluetoothInterface *, d->backendObject(), QString(), address()); +} + +QString Solid::Control::BluetoothInterface::version() const +{ + return_SOLID_CALL(Ifaces::BluetoothInterface *, d->backendObject(), QString(), version()); +} + +QString Solid::Control::BluetoothInterface::revision() const +{ + return_SOLID_CALL(Ifaces::BluetoothInterface *, d->backendObject(), QString(), revision()); +} + +QString Solid::Control::BluetoothInterface::manufacturer() const +{ + return_SOLID_CALL(Ifaces::BluetoothInterface *, d->backendObject(), QString(), manufacturer()); +} + +QString Solid::Control::BluetoothInterface::company() const +{ + return_SOLID_CALL(Ifaces::BluetoothInterface *, d->backendObject(), QString(), company()); +} + +Solid::Control::BluetoothInterface::Mode Solid::Control::BluetoothInterface::mode() const +{ + return_SOLID_CALL(Ifaces::BluetoothInterface *, d->backendObject(), Solid::Control::BluetoothInterface::Off, mode()); +} + +int Solid::Control::BluetoothInterface::discoverableTimeout() const +{ + return_SOLID_CALL(Ifaces::BluetoothInterface *, d->backendObject(), 0, discoverableTimeout()); +} + +bool Solid::Control::BluetoothInterface::isDiscoverable() const +{ + return_SOLID_CALL(Ifaces::BluetoothInterface *, d->backendObject(), false, isDiscoverable()); +} + +Solid::Control::BluetoothRemoteDeviceList Solid::Control::BluetoothInterface::listConnections() const +{ + BluetoothRemoteDeviceList list; + Ifaces::BluetoothInterface *backend = qobject_cast(d->backendObject()); + + if (backend == 0) return list; + + QStringList ubis = backend->listConnections(); + + foreach (const QString &ubi, ubis) { + BluetoothRemoteDevice remoteDevice = findBluetoothRemoteDevice(ubi); + list.append(remoteDevice); + } + + return list; +} + +QString Solid::Control::BluetoothInterface::majorClass() const +{ + return_SOLID_CALL(Ifaces::BluetoothInterface *, d->backendObject(), QString(), majorClass()); +} + +QStringList Solid::Control::BluetoothInterface::listAvailableMinorClasses() const +{ + return_SOLID_CALL(Ifaces::BluetoothInterface *, d->backendObject(), QStringList(), listAvailableMinorClasses()); +} + +QString Solid::Control::BluetoothInterface::minorClass() const +{ + return_SOLID_CALL(Ifaces::BluetoothInterface *, d->backendObject(), QString(), minorClass()); +} + +QStringList Solid::Control::BluetoothInterface::serviceClasses() const +{ + return_SOLID_CALL(Ifaces::BluetoothInterface *, d->backendObject(), QStringList(), serviceClasses()); +} + +QString Solid::Control::BluetoothInterface::name() const +{ + return_SOLID_CALL(Ifaces::BluetoothInterface *, d->backendObject(), QString(), name()); +} + +QString Solid::Control::BluetoothInterface::getRemoteName(const QString &mac) +{ + return_SOLID_CALL(Ifaces::BluetoothInterface *, d->backendObject(), QString(), getRemoteName(mac)); +} + +QStringList Solid::Control::BluetoothInterface::listBondings() const +{ + return_SOLID_CALL(Ifaces::BluetoothInterface *, d->backendObject(), QStringList(), listBondings()); +} + +bool Solid::Control::BluetoothInterface::isPeriodicDiscoveryActive() const +{ + return_SOLID_CALL(Ifaces::BluetoothInterface *, d->backendObject(), false, isPeriodicDiscoveryActive()); +} + +bool Solid::Control::BluetoothInterface::isPeriodicDiscoveryNameResolvingActive() const +{ + return_SOLID_CALL(Ifaces::BluetoothInterface *, d->backendObject(), false, + isPeriodicDiscoveryNameResolvingActive()); +} + +bool Solid::Control::BluetoothInterface::isTrusted(const QString& address) +{ + return_SOLID_CALL(Ifaces::BluetoothInterface *, d->backendObject(), false, isTrusted(address)); +} + +// TODO: QStringList or BluetoothRemoteDeviceList? +QStringList Solid::Control::BluetoothInterface::listRemoteDevices() const +{ + return_SOLID_CALL(Ifaces::BluetoothInterface *, d->backendObject(), QStringList(), + listRemoteDevices()); +} + +// TODO: QStringList or BluetoothRemoteDeviceList? +QStringList Solid::Control::BluetoothInterface::listRecentRemoteDevices(const QDateTime &date) const +{ + return_SOLID_CALL(Ifaces::BluetoothInterface *, d->backendObject(), QStringList(), + listRecentRemoteDevices(date)); +} + +*/ + +/***************************************************************/ +/* +void Solid::Control::BluetoothInterface::setMode(const Solid::Control::BluetoothInterface::Mode mode) +{ + SOLID_CALL(Ifaces::BluetoothInterface *, d->backendObject(), setMode(mode)); +} + +void Solid::Control::BluetoothInterface::setDiscoverableTimeout(int timeout) +{ + SOLID_CALL(Ifaces::BluetoothInterface *, d->backendObject(), setDiscoverableTimeout(timeout)); +} + +void Solid::Control::BluetoothInterface::setMinorClass(const QString &minor) +{ + SOLID_CALL(Ifaces::BluetoothInterface *, d->backendObject(), setMinorClass(minor)); +} + +void Solid::Control::BluetoothInterface::setName(const QString &name) +{ + SOLID_CALL(Ifaces::BluetoothInterface *, d->backendObject(), setName(name)); +} + +void Solid::Control::BluetoothInterface::discoverDevices() +{ + SOLID_CALL(Ifaces::BluetoothInterface *, d->backendObject(), discoverDevices()); +} + +void Solid::Control::BluetoothInterface::discoverDevicesWithoutNameResolving() +{ + SOLID_CALL(Ifaces::BluetoothInterface *, d->backendObject(), discoverDevicesWithoutNameResolving()); +} + +void Solid::Control::BluetoothInterface::cancelDiscovery() +{ + SOLID_CALL(Ifaces::BluetoothInterface *, d->backendObject(), cancelDiscovery()); +} + +void Solid::Control::BluetoothInterface::startPeriodicDiscovery() +{ + SOLID_CALL(Ifaces::BluetoothInterface *, d->backendObject(), startPeriodicDiscovery()); +} + +void Solid::Control::BluetoothInterface::stopPeriodicDiscovery() +{ + SOLID_CALL(Ifaces::BluetoothInterface *, d->backendObject(), stopPeriodicDiscovery()); +} + +void Solid::Control::BluetoothInterface::setPeriodicDiscoveryNameResolving(bool resolveNames) +{ + SOLID_CALL(Ifaces::BluetoothInterface *, d->backendObject(), setPeriodicDiscoveryNameResolving(resolveNames)); +} + +void Solid::Control::BluetoothInterface::setTrusted(const QString& address) +{ + SOLID_CALL(Ifaces::BluetoothInterface *, d->backendObject(), setTrusted(address)); +} + +void Solid::Control::BluetoothInterface::removeTrust(const QString& address) +{ + SOLID_CALL(Ifaces::BluetoothInterface *, d->backendObject(), removeTrust(address)); +} + +*/ + +void Solid::Control::BluetoothInterfacePrivate::setBackendObject(QObject *object) +{ + FrontendObjectPrivate::setBackendObject(object); + + if (object) { +/* + QObject::connect(object, SIGNAL(modeChanged(Solid::Control::BluetoothInterface::Mode)),parent(), SIGNAL(modeChanged(Solid::Control::BluetoothInterface::Mode))); + QObject::connect(object, SIGNAL(discoverableTimeoutChanged(int)), + parent(), SIGNAL(discoverableTimeoutChanged(int))); + QObject::connect(object, SIGNAL(minorClassChanged(const QString &)), + parent(), SIGNAL(minorClassChanged(const QString &))); + QObject::connect(object, SIGNAL(nameChanged(const QString &)), + parent(), SIGNAL(nameChanged(const QString &))); + QObject::connect(object, SIGNAL(discoveryStarted()), + parent(), SIGNAL(discoveryStarted())); + QObject::connect(object, SIGNAL(discoveryCompleted()), + parent(), SIGNAL(discoveryCompleted())); + QObject::connect(object, SIGNAL(remoteDeviceFound(const QString &, int, int)), + parent(), SIGNAL(remoteDeviceFound(const QString &, int, int))); + QObject::connect(object, SIGNAL(remoteDeviceDisappeared(const QString &)), + parent(), SIGNAL(remoteDeviceDisappeared(const QString &))); + QObject::connect(object, SIGNAL(remoteNameUpdated(const QString &,const QString &)), + parent(), SIGNAL(remoteNameUpdated(const QString &,const QString &))); + QObject::connect(object, SIGNAL(remoteDeviceConnected(const QString &)), + parent(), SIGNAL(remoteDeviceConnected(const QString &))); + QObject::connect(object, SIGNAL(remoteDeviceDisconnected(const QString &)), + parent(), SIGNAL(remoteDeviceDisconnected(const QString &))); + QObject::connect(object, SIGNAL(trustAdded(const QString &)), + parent(), SIGNAL(trustAdded(const QString &))); + QObject::connect(object, SIGNAL(trustRemoved(const QString &)), + parent(), SIGNAL(trustRemoved(const QString &))); + QObject::connect(object, SIGNAL(bondingCreated(const QString &)), + parent(), SIGNAL(bondingCreated(const QString &))); + QObject::connect(object, SIGNAL(bondingRemoved(const QString &)), + parent(), SIGNAL(bondingRemoved(const QString &))); +*/ + QObject::connect(object, SIGNAL(deviceCreated(const QString &)), + parent(), SIGNAL(deviceCreated(const QString &))); + QObject::connect(object, SIGNAL(deviceDisappeared(const QString &)), + parent(), SIGNAL(deviceDisappeared(const QString &))); + QObject::connect(object, SIGNAL(deviceFound(const QString &, const QMap &)), + parent(), SIGNAL(deviceFound(const QString &, const QMap &))); + QObject::connect(object, SIGNAL(deviceRemoved(const QString &)), + parent(), SIGNAL(deviceRemoved(const QString &))); + QObject::connect(object, SIGNAL(propertyChanged(const QString &,const QVariant &)), + parent(), SIGNAL(propertyChanged(const QString &, const QVariant &))); + + + + } +} + +QPair Solid::Control::BluetoothInterfacePrivate::findRegisteredBluetoothRemoteDevice(const QString &ubi) const +{ + if (remoteDeviceMap.contains(ubi)) { + return remoteDeviceMap[ubi]; + } else { + Ifaces::BluetoothInterface *backend = qobject_cast(backendObject()); + Ifaces::BluetoothRemoteDevice *iface = 0; + + if (backend != 0) { + iface = qobject_cast(backend->createBluetoothRemoteDevice(ubi)); + } + + if (iface != 0) { + BluetoothRemoteDevice *device = new BluetoothRemoteDevice(iface); + + QPair pair(device, iface); + remoteDeviceMap[ubi] = pair; + + return pair; + } else { + return QPair(0, 0); + } + + } +} + +#include "bluetoothinterface.moc" diff --git a/solid/control/bluetoothinterface.h b/solid/control/bluetoothinterface.h new file mode 100644 index 000000000..0ba4c463d --- /dev/null +++ b/solid/control/bluetoothinterface.h @@ -0,0 +1,558 @@ +/* This file is part of the KDE project + Copyright (C) 2006 Will Stephenson + Copyright (C) 2007 Daniel Gollub + + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#ifndef SOLID_CONTROL_BLUETOOTHINTERFACE_H +#define SOLID_CONTROL_BLUETOOTHINTERFACE_H + +#include +#include +#include +#include + +#include "bluetoothremotedevice.h" +#include "ifaces/bluetoothremotedevice.h" + + + +namespace Solid +{ +namespace Control +{ +class BluetoothRemoteDevice; +typedef QList BluetoothRemoteDeviceList; +class BluetoothInterfacePrivate; + +/** + * Represents a bluetooth interface as seen by the bluetooth subsystem. + */ +class SOLIDCONTROL_EXPORT BluetoothInterface : public QObject +{ + Q_OBJECT + +public: + /** + * Describes the operating mode of a bluetooth interface + * + * - Off : The interface's transceiver is turned off + * - Discoverable : The interface may be discovered by other devices and connected to + * - Connectable : The interface may only be connected to but not discovered + */ + //enum Mode { Off, Discoverable, Connectable }; + /** + * Constructs an invalid bluetooth interface + */ + BluetoothInterface(); + + /** + * Constructs a bluetooth interface for a given Unique Bluetooth Identifier (UBI). + * This object will be auto deleted, DON'T delete it. + * @param ubi the ubi of the bluetooth interface to create + */ + explicit BluetoothInterface(const QString &ubi); + + /** + * Constructs a new bluetooth interface taking its data from a backend. + * + * @param backendObject the object given by the backend + */ + explicit BluetoothInterface(QObject *backendObject); + + /** + * Constructs a copy of a bluetooth interface. + * + * @param device the bluetooth interface to copy + */ + BluetoothInterface(const BluetoothInterface &device); + + /** + * Destroys the device. + */ + ~BluetoothInterface(); + + + /** + * Assigns a bluetooth interface to this bluetooth interface and returns a reference to it. + * + * @param device the bluetooth interface to assign + * @return a reference to the bluetooth interface + */ + BluetoothInterface &operator=(const BluetoothInterface &device); + + /** + * Retrieves the Unique Bluetooth Identifier (UBI) of the BluetoothInterface. + * This identifier is ubique for each bluetooth and bluetooth interface in the system. + * + * @returns the Unique Bluetooth Identifier of the current bluetooth interface + */ + QString ubi() const; + + /** + * Create new BluetoothRemoteDevice object from this interface given its address. + * + * @param ubi the identifier of the bluetooth device to instantiate + * @returns a bluetooth object, if a bluetooth device having the given UBI, for this interface exists, 0 otherwise + */ + Solid::Control::BluetoothRemoteDevice* createBluetoothRemoteDevice(const QString &address); + + /** + * Finds a BluetoothRemoteDevice object given its UBI. + * + * @param ubi the identifier of the bluetooth remote device to find from this bluetooth interface + * @returns a valid BluetoothRemoteDevice object if a remote device having the given UBI for this interface exists, an invalid BluetoothRemoteDevice object otherwise. + */ + Solid::Control::BluetoothRemoteDevice findBluetoothRemoteDevice(const QString &address) const; + + /** + * Retrieves the MAC address of the bluetooth interface/adapter. + * + * @returns MAC address of bluetooth interface + */ + //QString address() const; + + /** + * Retrieves the version of the chip of the bluetooth interface/adapter. + * Example: "Bluetooth 2.0 + EDR" + * + * @returns bluetooth chip version + */ + //QString version() const; + + /** + * Retrieves the revision of the chip of the bluetooth interface/adapter. + * Example: "HCI 19.2" + * + * @returns bluetooth chip revision + */ + //QString revision() const; + + /** + * Retrieves the name of the bluetooth chip manufacturer. + * Example: "Boston Silicon Radio" + * + * @returns manufacturer string of bluetooth interface/adapter + */ + //QString manufacturer() const; + + /** + * Retrieves the name of the manufacturer of the bluetooth interface, + * using the chip supplied by BluetoothInterface::manufacterer() + * Based on device address. + * + * @returns company string of bluetooth interface/adapter + */ + //QString company() const; + + /** + * Retrieves the current mode of the bluetooth interface/adapter. + * + * @returns the current mode of bluetooth interface/adapter + */ + //Mode mode() const; + + /** + * Retrieves the discoverable timeout of the bluetooth interface/adapter. + * Discoverable timeout of 0 means never disappear. + * + * @returns current discoverable timeout in seconds + */ + //int discoverableTimeout() const; + + /** + * Retrieves the current discoverable staut of the bluetooth interface/adapter. + * + * @returns current discoverable status of bluetooth interface/adapter + */ + //bool isDiscoverable() const; + + /** + * List all UBIs of connected remote bluetooth devices of this handled bluetooth + * interface/adapter. + * + * @returns list UBIs of connected bluetooth remote devices + */ + //BluetoothRemoteDeviceList listConnections() const; + + /** + * Retrieves major class of the bluetooth interface/adapter. + * @todo enum + * @returns current major class of the bluetooth interface/adapter + */ + //QString majorClass() const; + + /** + * List supported minor classes of the bluetooth interface/adapter. + * @todo enum + * + * @returns list of supported minor classes by bluetooth interface/adapter + */ + //QStringList listAvailableMinorClasses() const; + + /** + * Retrieves minor class of the bluetooth interface/adapter. + * Valid classes, see listAvailableMinorClasses() + * @todo enum + * + * @returns minor class of the bluetooth interface/adapter. + */ + //QString minorClass() const; + + /** + * List services class of the bluetooth interface/adapter. + * @todo enum + * + * @returns list of service classes or empty list if no services registered + */ + //QStringList serviceClasses() const; + + /** + * Retrieves name of bluetooth interface/adapter. + * @todo enum + * + * @returns name of bluetooth interface/adapter + */ + //QString name() const; + + /** + * Returns the name of the remote device, given its mac address (mac). + * + * @return the name of the remote device + */ + //QString getRemoteName(const QString & mac); + + /** + * List UBIs of bonded/paired remote bluetooth devices with this bluetooth + * interface/adapter. + * + * @returns UBIs of bonded/paired bluetooth remote devices + */ + //QStringList listBondings() const; + + /** + * Periodic discovery status of this bluetooth interface/adapter. + * + * @returns true if periodic discovery is already active otherwise false + */ + // bool isPeriodicDiscoveryActive() const; + + /** + * Name resolving status of periodic discovery routing. + * + * @returns true if name got resolved while periodic discovery of this bluetooth + * interface/adapter + */ + //bool isPeriodicDiscoveryNameResolvingActive() const; + + /** + * List the Unique Bluetooth Identifier (UBI) of all known remote devices, + * whether they are seen, used or paired/bonded. + * + * See listConnections() + * + * @returns a QStringList of UBIs of all known remote bluetooth devices + */ + //QStringList listRemoteDevices() const; + + /** + * List the Unique Bluetooth Identifier (UBI) of all known remote devices since a specific + * datestamp. Known remote devices means remote bluetooth which are seen, used or + * paired/bonded. + * + * See listConnections(), listRemoteDevices() + * + * @param date the datestamp of the beginning of recent used devices + * @returns a QStringList of UBIs of all known remote bluetooth devices + */ + // QStringList listRecentRemoteDevices(const QDateTime &date) const; + + /** + * Returns true if the remote bluetooth device is trusted otherwise false. + * + * @param mac the address of the remote device + */ +// bool isTrusted(const QString &); + + + QString createPairedDevice(const QString &, const QString &, const QString &) const; + + QMap< QString, QVariant > getProperties() const; + + BluetoothRemoteDeviceList listDevices() const; + + + + +public Q_SLOTS: + /** + * Set mode of bluetooth interface/adapter. + * Valid modes, see mode() + * + * @param mode the mode of the bluetooth interface/adapter + */ + //void setMode(const Mode mode); + + /** + * Set discoverable timeout of bluetooth interface/adapter. + * + * @param timeout timeout in seconds + */ + //void setDiscoverableTimeout(int timeout); + + /** + * Set minor class of bluetooth interface/adapter. + * + * @param minor set minor class. Valid mode see listAvaliableMinorClasses() + */ + //void setMinorClass(const QString &minor); + + /** + * Set name of bluetooth interface/adapter. + * + * @param name the name of bluetooth interface/adapter + */ + //void setName(const QString &name); + + /** + * Start discovery of remote bluetooth devices with device name resolving. + */ + //void discoverDevices(); + /** + * Start discovery of remote bluetooth devices without device name resolving. + */ + //void discoverDevicesWithoutNameResolving(); + /** + * Cancel discovery of remote bluetooth devices. + */ + //void cancelDiscovery(); + + /** + * Start periodic discovery of remote bluetooth devices. + * See stopPeriodicDiscovery() + */ + //void startPeriodicDiscovery(); + + /** + * Stop periodic discovery of remote bluetooth devices. + */ + //void stopPeriodicDiscovery(); + + /** + * Enable/Disable name resolving of remote bluetooth devices in periodic discovery. + * + * @param resolveName true to enable name resolving otherwise false + */ + //void setPeriodicDiscoveryNameResolving(bool resolveNames); + + /** + * Marks the device as trusted. + * + * @param mac the address of the remote device + */ + //void setTrusted(const QString &); + + /** + * Marks the device as not trusted. + * + * @param mac the address of the remote device + */ + //void removeTrust(const QString &); + + void registerAgent(const QString &,const QString &) const; + + void releaseSession() const; + + void removeDevice(const QString &) const; + + void requestSession() const; + + void setProperty(const QString &, const QVariant &) const; + + void startDiscovery() const; + + void stopDiscovery() const; + + void unregisterAgent(const QString &) const; + + void cancelDeviceCreation(const QString &) const; + + + +Q_SIGNALS: + + /** + * This signal is emitted if the mode of the bluetooth interface/adapter has changed. + * See mode() for valid modes. + * + * @param mode the changed mode + */ + //void modeChanged(Solid::Control::BluetoothInterface::Mode); + + /** + * The signal is emitted if the discoverable timeout of the bluetooth interface/adapter + * has changed. + * + * @param timeout the changed timeout in seconds + */ + //void discoverableTimeoutChanged(int timeout); + + /** + * The signal is emitted if the minor class of the bluetooth interface/adapter has changed. + * + * @param minor the new minor class + */ + //void minorClassChanged(const QString &minor); + + /** + * The signal is emitted if the name of the bluetooth interface/adapter has changed. + * + * @param name the new name of the device + */ + //void nameChanged(const QString &name); + + /** + * This signal is emitted if a discovery has started. + */ + //void discoveryStarted(); + + /** + * This signal is emitted if a discovery has completed. + */ + //void discoveryCompleted(); + + /** + * This signal is emitted if the bluetooth interface/adapter detects a new remote bluetooth device. + * + * @todo change arguments types of deviceClass (uint32) and rssi (int16) + * + * @param ubi the new bluetooth identifier + * @param deviceClass the device class of the remote device + * @param rssi the Received Signal Strength Information (RSSI) of the remote device + */ + //void remoteDeviceFound(const QString &ubi, int deviceClass, int rssi); + + /** + * This signal is emitted if the bluetooth interface/adapter detectes a bluetooth device + * disappeared. + * + * @param ubi the ubi of the disappering bluetooth remote device + */ + //void remoteDeviceDisappeared(const QString &ubi); + + /** + * This signal is emitted if the bluetooth interface/adapter detectes a new name for a + * bluetooth device. + * + * @param address the address of the bluetooth remote device + * @param name the name of the bluetooth remote device + */ + //void remoteNameUpdated(const QString &address, const QString &name); + + /** + * This signal is emitted if a bluetooth connection has been created. + * + * @param address the address of the connected bluetooth remote device + */ + //void remoteDeviceConnected(const QString &address); + + /** + * This signal is emitted if a bluetooth connection has been terminated. + * + * @param address the address of the disconnected bluetooth remote device + */ + //void remoteDeviceDisconnected(const QString &address); + + /** + * This signal is emitted if a bluetooth device was set trusted. + * + * @param address the address of the trusted bluetooth remote device + */ + //void trustAdded(const QString &address); + + /** + * This signal is emitted if the trust to the bluetooth device was removed. + * + * @param address the address of the bluetooth remote device + */ + //void trustRemoved(const QString &address); + + /** + * This signal is emitted if a successful bonding has been created. + * + * @param address the address of the bluetooth remote device + */ + //void bondingCreated(const QString &address); + + /** + * This signal is emitted if the bonding to a bluetooth device has been removed. + * + * @param address the address of the bluetooth remote device + */ + //void bondingRemoved(const QString &address); +/** + * This signal is emitted when a remote device is created. + * + * @param ubi the object path of the device on the system bus + */ + void deviceCreated(const QString &ubi); + + /** + * This signal is emitted when an inquiry session for a periodic discovery finishes and previously found + * devices are no longer in range or visible. + * + * @param address the address of the remote device + */ + void deviceDisappeared(const QString &address); + + /** + * This signal will be emitted every time an inquiry result has been found by the service daemon. + * In general they only appear during a device discovery. + * + * @param address the address of the remote device + * @param properties the properties of the remote device + */ + void deviceFound(const QString &address, const QMap< QString, QVariant > &properties); + + /** + * This signal is emitted when a remote device is removed from the system bus. + * + * @param ubi the object path on the system bus from the remote device + */ + void deviceRemoved(const QString &ubi); + + /** + * This signal is emitted when a property of the adapter is set to a new value. + * + * @param property the named property of the adapter + * @value the new value for the property + */ + void propertyChanged(const QString &property, const QVariant &value); + + +private: + Q_PRIVATE_SLOT(d, void _k_destroyed(QObject *)) + + BluetoothInterfacePrivate * const d; +}; + +} //Control +} //Solid + +#endif + diff --git a/solid/control/bluetoothmanager.cpp b/solid/control/bluetoothmanager.cpp new file mode 100644 index 000000000..64ac8db45 --- /dev/null +++ b/solid/control/bluetoothmanager.cpp @@ -0,0 +1,391 @@ +/* This file is part of the KDE project + Copyright (C) 2006 Will Stephenson + Copyright (C) 2006 Kévin Ottens + Copyright (C) 2007 Daniel Gollub + Copyright (C) 2008 Tom Patzig + + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#include +#include +#include + +#include "ifaces/bluetoothmanager.h" +#include "ifaces/bluetoothinterface.h" +#include "ifaces/bluetoothinputdevice.h" +#include "ifaces/bluetoothsecurity.h" + +#include "soliddefs_p.h" +#include "managerbase_p.h" + +#include "bluetoothinterface.h" +#include "bluetoothmanager.h" +#include "bluetoothsecurity.h" + +#include + +namespace Solid +{ +namespace Control +{ +class BluetoothManagerPrivate : public ManagerBasePrivate +{ +public: + BluetoothManagerPrivate(BluetoothManager *parent) + : q(parent) { } + + BluetoothManager * const q; + + QPair findRegisteredBluetoothInterface(const QString &ubi) const; + QPair findRegisteredBluetoothInputDevice(const QString &ubi) const; + + void connectBackend(QObject *newBackend); + + void _k_interfaceAdded(const QString &ubi); + void _k_interfaceRemoved(const QString &ubi); + void _k_interfaceDestroyed(QObject *object); +/* + void _k_inputDeviceCreated(const QString &ubi); + void _k_inputDeviceRemoved(const QString &ubi); + void _k_inputDeviceDestroyed(QObject *object); +*/ + + mutable QMap > bluetoothInterfaceMap; + mutable QMap > bluetoothInputDeviceMap; + + BluetoothInterface invalidInterface; + BluetoothInputDevice invalidInputDevice; +}; +} +} + +SOLID_SINGLETON_IMPLEMENTATION(Solid::Control::BluetoothManager, BluetoothManager) + + +Solid::Control::BluetoothManager::BluetoothManager() + : QObject(), d(new BluetoothManagerPrivate(this)) +{ + d->loadBackend("Bluetooth Management", + "SolidBluetoothManager", + "Solid::Control::Ifaces::BluetoothManager"); + + if (d->managerBackend() != 0) { + d->connectBackend(d->managerBackend()); + } +} + +Solid::Control::BluetoothManager::~BluetoothManager() +{ + // Delete all the interfaces, they are now outdated + typedef QPair BluetoothInterfaceIfacePair; + + // Delete all the devices, they are now outdated + foreach (const BluetoothInterfaceIfacePair &pair, d->bluetoothInterfaceMap) { + delete pair.first; + delete pair.second; + } + + d->bluetoothInterfaceMap.clear(); +} +/* +Solid::Control::BluetoothInterfaceList Solid::Control::BluetoothManager::buildDeviceList(const QStringList & ubiList) const +{ + BluetoothInterfaceList list; + Ifaces::BluetoothManager *backend = qobject_cast(d->managerBackend()); + + if (backend == 0) return list; + + foreach (const QString &ubi, ubiList) { + QPair pair = d->findRegisteredBluetoothInterface(ubi); + + if (pair.first != 0) { + list.append(*pair.first); + } + } + + return list; +} +*/ +/* +Solid::Control::BluetoothInterfaceList Solid::Control::BluetoothManager::bluetoothInterfaces() const +{ + Ifaces::BluetoothManager *backend = qobject_cast(d->managerBackend()); + + if (backend != 0) { + return buildDeviceList(backend->bluetoothInterfaces()); + } else { + return BluetoothInterfaceList(); + } +} +*/ +QStringList Solid::Control::BluetoothManager::bluetoothInterfaces() const +{ + return_SOLID_CALL(Ifaces::BluetoothManager *, d->managerBackend(), QStringList(), bluetoothInterfaces()); +} + +QString Solid::Control::BluetoothManager::defaultInterface() const +{ + return_SOLID_CALL(Ifaces::BluetoothManager *, d->managerBackend(), QString(), defaultInterface()); +} + +Solid::Control::BluetoothInterface Solid::Control::BluetoothManager::findBluetoothInterface(const QString &ubi) const +{ + Ifaces::BluetoothManager *backend = qobject_cast(d->managerBackend()); + + if (backend == 0) return d->invalidInterface; + + QPair pair = d->findRegisteredBluetoothInterface(ubi); + + if (pair.first != 0) { + return *pair.first; + } else { + return d->invalidInterface; + } +} + +QString Solid::Control::BluetoothManager::findInterface(const QString &dev) const +{ + return_SOLID_CALL(Ifaces::BluetoothManager *, d->managerBackend(), QString(), findInterface(dev)); +} + +/* +Solid::Control::BluetoothInputDevice Solid::Control::BluetoothManager::findBluetoothInputDevice(const QString &ubi) const +{ + Ifaces::BluetoothManager *backend = qobject_cast(d->managerBackend()); + + if (backend == 0) return d->invalidInputDevice; + + QPair pair = d->findRegisteredBluetoothInputDevice(ubi); + + if (pair.first != 0) { + return *pair.first; + } else { + return d->invalidInputDevice; + } +} +*/ + +/* +Solid::Control::BluetoothInputDevice* Solid::Control::BluetoothManager::createBluetoothInputDevice(const QString &ubi) +{ + Ifaces::BluetoothManager *backend = qobject_cast(d->managerBackend()); + Ifaces::BluetoothInputDevice *iface = 0; + if (backend != 0) { + iface = qobject_cast(backend->createBluetoothInputDevice(ubi)); + } + if (iface != 0) { + BluetoothInputDevice *device = new BluetoothInputDevice(iface); + return device; + + } else { + return &d->invalidInputDevice; + } + +} + +KJob *Solid::Control::BluetoothManager::setupInputDevice(const QString &ubi) +{ + return_SOLID_CALL(Ifaces::BluetoothManager *, d->managerBackend(), 0, setupInputDevice(ubi)); +} + +Solid::Control::BluetoothInputDeviceList Solid::Control::BluetoothManager::bluetoothInputDevices() const +{ + BluetoothInputDeviceList list; + Ifaces::BluetoothManager *backend = qobject_cast(d->managerBackend()); + + if (backend == 0) return list; + + QStringList ubis = backend->bluetoothInputDevices(); + + foreach (const QString &ubi, ubis) { + QPair pair = d->findRegisteredBluetoothInputDevice(ubi); + + if (pair.first != 0) { + list.append(*pair.first); + } + } + return list; +} + +Solid::Control::BluetoothSecurity *Solid::Control::BluetoothManager::security(const QString &interface) +{ + Ifaces::BluetoothManager *backendManager = qobject_cast(d->managerBackend()); + if (backendManager!=0) { + Ifaces::BluetoothSecurity *backendSecurity = backendManager->security(interface); + return new Solid::Control::BluetoothSecurity(backendSecurity); + } + return 0; +} + +void Solid::Control::BluetoothManager::removeInputDevice(const QString &ubi) +{ + SOLID_CALL(Ifaces::BluetoothManager *, d->managerBackend(), removeInputDevice(ubi)); +} +*/ +void Solid::Control::BluetoothManagerPrivate::_k_interfaceAdded(const QString &ubi) +{ + QPair pair = bluetoothInterfaceMap.take(ubi); + + if (pair.first != 0) { + // Oops, I'm not sure it should happen... + // But well in this case we'd better kill the old device we got, it's probably outdated + + delete pair.first; + delete pair.second; + } + + emit q->interfaceAdded(ubi); +} + +void Solid::Control::BluetoothManagerPrivate::_k_interfaceRemoved(const QString &ubi) +{ + QPair pair = bluetoothInterfaceMap.take(ubi); + + if (pair.first != 0) { + delete pair.first; + delete pair.second; + } + + emit q->interfaceRemoved(ubi); +} + +void Solid::Control::BluetoothManagerPrivate::_k_interfaceDestroyed(QObject *object) +{ + Ifaces::BluetoothInterface *device = qobject_cast(object); + + if (device != 0) { + QString ubi = device->ubi(); + QPair pair = bluetoothInterfaceMap.take(ubi); + delete pair.first; + } +} + +/* +void Solid::Control::BluetoothManagerPrivate::_k_inputDeviceCreated(const QString &ubi) +{ + QPair pair = bluetoothInputDeviceMap.take(ubi); + + if (pair.first != 0) { + // Oops, I'm not sure it should happen... + // But well in this case we'd better kill the old device we got, it's probably outdated + + delete pair.first; + delete pair.second; + } + + emit q->inputDeviceCreated(ubi); +} + +void Solid::Control::BluetoothManagerPrivate::_k_inputDeviceRemoved(const QString &ubi) +{ + QPair pair = bluetoothInputDeviceMap.take(ubi); + + if (pair.first != 0) { + delete pair.first; + delete pair.second; + } + + emit q->inputDeviceRemoved(ubi); +} + +void Solid::Control::BluetoothManagerPrivate::_k_inputDeviceDestroyed(QObject *object) +{ + Ifaces::BluetoothInputDevice *device = qobject_cast(object); + + if (device != 0) { + QString ubi = device->ubi(); + QPair pair = bluetoothInputDeviceMap.take(ubi); + delete pair.first; + } +} +*/ + +/***************************************************************************/ + +void Solid::Control::BluetoothManagerPrivate::connectBackend(QObject *newBackend) +{ + QObject::connect(newBackend, SIGNAL(interfaceAdded(const QString &)), + q, SLOT(_k_interfaceAdded(const QString &))); + QObject::connect(newBackend, SIGNAL(interfaceRemoved(const QString &)), + q, SLOT(_k_interfaceRemoved(const QString &))); +/* + QObject::connect(newBackend, SIGNAL(inputDeviceCreated(const QString &)), + q, SLOT(_k_inputDeviceCreated(const QString &))); + QObject::connect(newBackend, SIGNAL(inputDeviceRemoved(const QString &)), + q, SLOT(_k_inputDeviceRemoved(const QString &))); +*/ + +} + +QPair Solid::Control::BluetoothManagerPrivate::findRegisteredBluetoothInterface(const QString &ubi) const +{ + if (bluetoothInterfaceMap.contains(ubi)) { + return bluetoothInterfaceMap[ubi]; + } else { + Ifaces::BluetoothManager *backend = qobject_cast(managerBackend()); + Ifaces::BluetoothInterface *iface = 0; + + if (backend != 0) { + iface = qobject_cast(backend->createInterface(ubi)); + } + + if (iface != 0) { + BluetoothInterface *device = new BluetoothInterface(iface); + QPair pair(device, iface); + QObject::connect(iface, SIGNAL(destroyed(QObject *)), + q, SLOT(_k_interfaceDestroyed(QObject *))); + bluetoothInterfaceMap[ubi] = pair; + return pair; + } else { + return QPair(0, 0); + } + } +} + +/* +QPair Solid::Control::BluetoothManagerPrivate::findRegisteredBluetoothInputDevice(const QString &ubi) const +{ + + if (bluetoothInputDeviceMap.contains(ubi)) { + return bluetoothInputDeviceMap[ubi]; + } else { + Ifaces::BluetoothManager *backend = qobject_cast(managerBackend()); + Ifaces::BluetoothInputDevice *iface = 0; + + if (backend != 0) { + iface = qobject_cast(backend->createBluetoothInputDevice(ubi)); + } + + if (iface != 0) { + BluetoothInputDevice *device = new BluetoothInputDevice(iface); + QPair pair(device, iface); + bluetoothInputDeviceMap[ubi] = pair; + QObject::connect(iface, SIGNAL(destroyed(QObject *)), + q, SLOT(_k_inputDeviceDestroyed(QObject *))); + return pair; + } else { + return QPair(0, 0); + } + } +} +*/ + + + + +#include "bluetoothmanager.moc" diff --git a/solid/control/bluetoothmanager.h b/solid/control/bluetoothmanager.h new file mode 100644 index 000000000..749917d3c --- /dev/null +++ b/solid/control/bluetoothmanager.h @@ -0,0 +1,204 @@ +/* This file is part of the KDE project + Copyright (C) 2006 Will Stephenson + Copyright (C) 2006 Kevin Ottens + Copyright (C) 2007 Daniel Gollub + Copyright (C) 2008 Tom Patzig + + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#ifndef SOLID_CONTROL_BLUETOOTHMANAGER_H +#define SOLID_CONTROL_BLUETOOTHMANAGER_H + +#include + +#include "singletondefs.h" +#include "solid_control_export.h" + +#include "bluetoothinterface.h" +#include "bluetoothinputdevice.h" + +class KJob; + +namespace Solid +{ +namespace Control +{ +namespace Ifaces +{ + class BluetoothManager; +} + +class BluetoothInterface; +class BluetoothSecurity; + +typedef QList BluetoothInterfaceList; +typedef QList BluetoothInputDeviceList; +class BluetoothManagerPrivate; + +/** + * This class specifies the interface a backend will have to implement in + * order to be used in the system. + * + * A bluetooth manager allow to query the underlying platform to discover the + * available bluetooth interfaces. + */ +class SOLIDCONTROL_EXPORT BluetoothManager : public QObject +{ + Q_OBJECT + SOLID_SINGLETON(BluetoothManager) + +public: + /** + * Retrieves the list of all the bluetooth interfaces Universal Bluetooth Identifiers (UBIs) + * in the system. + * + * @return the list of bluetooth interfaces available in this system + */ + //BluetoothInterfaceList bluetoothInterfaces() const; + QStringList bluetoothInterfaces() const; + + /** + * Retrieves the default bluetooth interface Universal Bluetooth Identifiers (UBIs) + * of the system. + * + * @return the UBI of the default bluetooth interface + */ + QString defaultInterface() const; + + /** + * Returns the UBI of the Bluetooth Interface given its name (e.g. 'hci0'), + * if found on the system. + * + * @return the found UBI of the named bluetooth interface + */ + QString findInterface(const QString & name) const; + + + /** + * Find a new BluetoothInterface object given its UBI. + * + * @param ubi the identifier of the bluetooth interface to find + * @returns a valid BlueoothInterface object if there's a device having the given UBI, an invalid one otherwise + */ + BluetoothInterface findBluetoothInterface(const QString & ubi) const; + + + /** + * Find a new BluetoothInputDevice object given its UBI. + * + * @param ubi the identifier of the bluetooth input device to find + * @returns a valid BlueoothInputDevice object if there's a device having the given UBI, an invalid one otherwise + */ + // BluetoothInputDevice findBluetoothInputDevice(const QString & ubi) const; + + /** + * Retrieves the list of Universal Bluetooth Identifiers (UBIs) of bluetooth input devices + * which are configured in the system. Configured means also not connected devices. + * + * @return the list of bluetooth input devices configured in this system + */ + //BluetoothInputDeviceList bluetoothInputDevices() const; + + /** + * Instantiates a new BluetoothInputDevice object from this backend given its UBI. + * + * @param ubi the identifier of the bluetooth input device instantiated + * @returns a new BluetoothInputDevice object if there's a device having the given UBI, 0 otherwise + */ + //BluetoothInputDevice *createBluetoothInputDevice(const QString &ubi); + + /** + * Setup a new bluetooth input device. + * + * @param ubi the ubi of the bluetooth input device + * @returns the job handling of the operation. + */ + //KJob *setupInputDevice(const QString &ubi); + + /** + * Gets an instance of BluetoothSecurity to handle pairing/authorization requests + */ + //BluetoothSecurity *security(const QString &interface = QString()); + +public Q_SLOTS: + /** + * Remove the configuraiton of a bluetooth input device. + * + * @param ubi the bluetooth input device identifier + */ +// void removeInputDevice(const QString & ubi); + +Q_SIGNALS: + /** + * This signal is emitted when a new bluetooth interface is available. + * + * @param ubi the bluetooth interface identifier + */ + void interfaceAdded(const QString & ubi); + + /** + * This signal is emitted when a bluetooth interface is not available anymore. + * + * @param ubi the bluetooth interface identifier + */ + void interfaceRemoved(const QString & ubi); + + /** + * This signal is emitted when the default bluetooth interface changed. + * + * @param ubi the bluetooth interface identifier + */ + void defaultInterfaceChanged(const QString & ubi); + + /** + * This signal is emitted when a new bluetooth input device got configured/created. + * + * @param ubi the bluetooth input device identifier + */ +// void inputDeviceCreated(const QString & ubi); + + /** + * This signal is emitted when a bluetooth input device configuration is not available anymore. + * + * @param ubi the bluetooth input device identifier + */ +// void inputDeviceRemoved(const QString & ubi); + + +private: + BluetoothManager(); + ~BluetoothManager(); + + //BluetoothInterfaceList buildDeviceList(const QStringList & ubiList) const; + + Q_PRIVATE_SLOT(d, void _k_interfaceAdded(const QString &)) + Q_PRIVATE_SLOT(d, void _k_interfaceRemoved(const QString &)) + Q_PRIVATE_SLOT(d, void _k_interfaceDestroyed(QObject *)) +/* + Q_PRIVATE_SLOT(d, void _k_inputDeviceCreated(const QString &)) + Q_PRIVATE_SLOT(d, void _k_inputDeviceRemoved(const QString &)) + Q_PRIVATE_SLOT(d, void _k_inputDeviceDestroyed(QObject *)) +*/ + + BluetoothManagerPrivate * const d; + friend class BluetoothManagerPrivate; +}; +} // Control +} // Solid + +#endif diff --git a/solid/control/bluetoothremotedevice.cpp b/solid/control/bluetoothremotedevice.cpp new file mode 100644 index 000000000..d9ec38d93 --- /dev/null +++ b/solid/control/bluetoothremotedevice.cpp @@ -0,0 +1,315 @@ +/* This file is part of the KDE project + Copyright (C) 2006 Will Stephenson + Copyright (C) 2007 Daniel Gollub + Copyright (C) 2008 Tom Patzig + + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#include +#include + +#include "ifaces/bluetoothremotedevice.h" + +#include "frontendobject_p.h" + +#include "soliddefs_p.h" +#include "bluetoothmanager.h" +#include "bluetoothinterface.h" + +namespace Solid +{ +namespace Control +{ + class BluetoothRemoteDevicePrivate : public FrontendObjectPrivate + { + public: + BluetoothRemoteDevicePrivate(QObject *parent) + : FrontendObjectPrivate(parent) { } + + void setBackendObject(QObject *object); + }; +} +} + +Solid::Control::BluetoothRemoteDevice::BluetoothRemoteDevice(QObject *backendObject) + : QObject(), d_ptr(new BluetoothRemoteDevicePrivate(this)) +{ + Q_D(BluetoothRemoteDevice); + d->setBackendObject(backendObject); +} + +Solid::Control::BluetoothRemoteDevice::BluetoothRemoteDevice(const BluetoothRemoteDevice &device) + : QObject(), d_ptr(new BluetoothRemoteDevicePrivate(this)) +{ + Q_D(BluetoothRemoteDevice); + d->setBackendObject(device.d_ptr->backendObject()); +} + +Solid::Control::BluetoothRemoteDevice::~BluetoothRemoteDevice() +{} + +Solid::Control::BluetoothRemoteDevice &Solid::Control::BluetoothRemoteDevice::operator=(const Solid::Control::BluetoothRemoteDevice & dev) +{ + Q_D(BluetoothRemoteDevice); + d->setBackendObject(dev.d_ptr->backendObject()); + + return *this; +} + +bool Solid::Control::BluetoothRemoteDevice::operator==(const BluetoothRemoteDevice & other) const +{ + return ubi() == other.ubi(); +} + +QString Solid::Control::BluetoothRemoteDevice::ubi() const +{ + Q_D(const BluetoothRemoteDevice); + return_SOLID_CALL(Ifaces::BluetoothRemoteDevice *, d->backendObject(), QString(), ubi()); +} + +QMap Solid::Control::BluetoothRemoteDevice::getProperties() +{ + Q_D(const BluetoothRemoteDevice); + return_SOLID_CALL(Ifaces::BluetoothRemoteDevice *, d->backendObject(), (QMap< QString,QVariant >()), getProperties()); +} + +QStringList Solid::Control::BluetoothRemoteDevice::listNodes() +{ + Q_D(const BluetoothRemoteDevice); + return_SOLID_CALL(Ifaces::BluetoothRemoteDevice *, d->backendObject(), QStringList(), listNodes()); +} + +void Solid::Control::BluetoothRemoteDevice::setProperty(const QString &name, const QVariant &value) +{ + Q_D(const BluetoothRemoteDevice); + SOLID_CALL(Ifaces::BluetoothRemoteDevice *, d->backendObject(), setProperty(name,value)); +} + +void Solid::Control::BluetoothRemoteDevice::cancelDiscovery() +{ + Q_D(const BluetoothRemoteDevice); + SOLID_CALL(Ifaces::BluetoothRemoteDevice *, d->backendObject(), cancelDiscovery()); +} + +void Solid::Control::BluetoothRemoteDevice::disconnect() +{ + Q_D(const BluetoothRemoteDevice); + SOLID_CALL(Ifaces::BluetoothRemoteDevice *, d->backendObject(), disconnect()); +} + + + +/* +QString Solid::Control::BluetoothRemoteDevice::address() const +{ + Q_D(const BluetoothRemoteDevice); + return_SOLID_CALL(Ifaces::BluetoothRemoteDevice *, d->backendObject(), QString(), address()); +} + +bool Solid::Control::BluetoothRemoteDevice::isConnected() const +{ + Q_D(const BluetoothRemoteDevice); + return_SOLID_CALL(Ifaces::BluetoothRemoteDevice *, d->backendObject(), false, isConnected()); +} + +QString Solid::Control::BluetoothRemoteDevice::version() const +{ + Q_D(const BluetoothRemoteDevice); + return_SOLID_CALL(Ifaces::BluetoothRemoteDevice *, d->backendObject(), QString(), version()); +} + +QString Solid::Control::BluetoothRemoteDevice::revision() const +{ + Q_D(const BluetoothRemoteDevice); + return_SOLID_CALL(Ifaces::BluetoothRemoteDevice *, d->backendObject(), QString(), revision()); +} + +QString Solid::Control::BluetoothRemoteDevice::manufacturer() const +{ + Q_D(const BluetoothRemoteDevice); + return_SOLID_CALL(Ifaces::BluetoothRemoteDevice *, d->backendObject(), QString(), manufacturer()); +} + +QString Solid::Control::BluetoothRemoteDevice::company() const +{ + Q_D(const BluetoothRemoteDevice); + return_SOLID_CALL(Ifaces::BluetoothRemoteDevice *, d->backendObject(), QString(), company()); +} + +QString Solid::Control::BluetoothRemoteDevice::majorClass() const +{ + Q_D(const BluetoothRemoteDevice); + return_SOLID_CALL(Ifaces::BluetoothRemoteDevice *, d->backendObject(), QString(), majorClass()); +} + +QString Solid::Control::BluetoothRemoteDevice::minorClass() const +{ + Q_D(const BluetoothRemoteDevice); + return_SOLID_CALL(Ifaces::BluetoothRemoteDevice *, d->backendObject(), QString(), minorClass()); +} + +QStringList Solid::Control::BluetoothRemoteDevice::serviceClasses() const +{ + Q_D(const BluetoothRemoteDevice); + return_SOLID_CALL(Ifaces::BluetoothRemoteDevice *, d->backendObject(), QStringList(), serviceClasses()); +} +QString Solid::Control::BluetoothRemoteDevice::name() const +{ + Q_D(const BluetoothRemoteDevice); + return_SOLID_CALL(Ifaces::BluetoothRemoteDevice *, d->backendObject(), QString(), name()); +} + +QString Solid::Control::BluetoothRemoteDevice::alias() const +{ + Q_D(const BluetoothRemoteDevice); + return_SOLID_CALL(Ifaces::BluetoothRemoteDevice *, d->backendObject(), QString(), alias()); +} + +QString Solid::Control::BluetoothRemoteDevice::lastSeen() const +{ + Q_D(const BluetoothRemoteDevice); + return_SOLID_CALL(Ifaces::BluetoothRemoteDevice *, d->backendObject(), QString(), lastSeen()); +} + +QString Solid::Control::BluetoothRemoteDevice::lastUsed() const +{ + Q_D(const BluetoothRemoteDevice); + return_SOLID_CALL(Ifaces::BluetoothRemoteDevice *, d->backendObject(), QString(), lastUsed()); +} + +bool Solid::Control::BluetoothRemoteDevice::hasBonding() const +{ + Q_D(const BluetoothRemoteDevice); + return_SOLID_CALL(Ifaces::BluetoothRemoteDevice *, d->backendObject(), false, hasBonding()); +} + +int Solid::Control::BluetoothRemoteDevice::pinCodeLength() const +{ + Q_D(const BluetoothRemoteDevice); + return_SOLID_CALL(Ifaces::BluetoothRemoteDevice *, d->backendObject(), 0, pinCodeLength()); +} + +int Solid::Control::BluetoothRemoteDevice::encryptionKeySize() const +{ + Q_D(const BluetoothRemoteDevice); + return_SOLID_CALL(Ifaces::BluetoothRemoteDevice *, d->backendObject(), 0, encryptionKeySize()); +} + +KJob *Solid::Control::BluetoothRemoteDevice::createBonding() +{ + Q_D(BluetoothRemoteDevice); + return_SOLID_CALL(Ifaces::BluetoothRemoteDevice *, d->backendObject(), 0, createBonding()); +} + +void Solid::Control::BluetoothRemoteDevice::setAlias(const QString &alias) +{ + Q_D(BluetoothRemoteDevice); + SOLID_CALL(Ifaces::BluetoothRemoteDevice *, d->backendObject(), setAlias(alias)); +} + +void Solid::Control::BluetoothRemoteDevice::clearAlias() +{ + Q_D(BluetoothRemoteDevice); + SOLID_CALL(Ifaces::BluetoothRemoteDevice *, d->backendObject(), clearAlias()); +} + +void Solid::Control::BluetoothRemoteDevice::disconnect() +{ + Q_D(BluetoothRemoteDevice); + SOLID_CALL(Ifaces::BluetoothRemoteDevice *, d->backendObject(), disconnect()); +} + +void Solid::Control::BluetoothRemoteDevice::cancelBondingProcess() +{ + Q_D(BluetoothRemoteDevice); + SOLID_CALL(Ifaces::BluetoothRemoteDevice *, d->backendObject(), cancelBondingProcess()); +} + +void Solid::Control::BluetoothRemoteDevice::removeBonding() +{ + Q_D(const BluetoothRemoteDevice); + SOLID_CALL(Ifaces::BluetoothRemoteDevice *, d->backendObject(), removeBonding()); +} +void Solid::Control::BluetoothRemoteDevice::serviceHandles(const QString &filter) const +{ + Q_D(const BluetoothRemoteDevice); + SOLID_CALL(Ifaces::BluetoothRemoteDevice *, d->backendObject(), serviceHandles(filter)); +} + +void Solid::Control::BluetoothRemoteDevice::serviceRecordAsXml(uint handle) const +{ + Q_D(const BluetoothRemoteDevice); + SOLID_CALL(Ifaces::BluetoothRemoteDevice *, d->backendObject(), serviceRecordAsXml(handle)); +} +*/ + +void Solid::Control::BluetoothRemoteDevice::discoverServices(const QString &filter) +{ + Q_D(const BluetoothRemoteDevice); + SOLID_CALL(Ifaces::BluetoothRemoteDevice *, d->backendObject(), discoverServices(filter)); +} + +void Solid::Control::BluetoothRemoteDevicePrivate::setBackendObject(QObject *object) +{ + FrontendObjectPrivate::setBackendObject(object); + + if (object) { + /* + QObject::connect(object, SIGNAL(classChanged(uint)), + parent(), SIGNAL(classChanged(uint))); + QObject::connect(object, SIGNAL(nameChanged(const QString &)), + parent(), SIGNAL(nameChanged(const QString &))); + QObject::connect(object, SIGNAL(nameResolvingFailed()), + parent(), SIGNAL(nameResolvingFailed())); + QObject::connect(object, SIGNAL(aliasChanged(const QString &)), + parent(), SIGNAL(aliasChanged(const QString &))); + QObject::connect(object, SIGNAL(aliasCleared()), + parent(), SIGNAL(aliasCleared())); + QObject::connect(object, SIGNAL(connected()), + parent(), SIGNAL(connected())); + QObject::connect(object, SIGNAL(requestDisconnection()), + parent(), SIGNAL(requestDisconnection())); + QObject::connect(object, SIGNAL(disconnected()), + parent(), SIGNAL(disconnected())); + QObject::connect(object, SIGNAL(bondingCreated()), + parent(), SIGNAL(bondingCreated())); + QObject::connect(object, SIGNAL(bondingRemoved()), + parent(), SIGNAL(bondingRemoved())); + QObject::connect(object, SIGNAL(serviceHandlesAvailable(const QString &, const QList &)), + parent(), SIGNAL(serviceHandlesAvailable(const QString &, const QList &))); + QObject::connect(object, SIGNAL(serviceRecordXmlAvailable(const QString &, const QString &)), + parent(), SIGNAL(serviceRecordXmlAvailable(const QString &, const QString &))); + */ + + QObject::connect(object, SIGNAL(serviceDiscoverAvailable(const QString &, const QMap< uint,QString> &)), + parent(), SIGNAL(serviceDiscoverAvailable(const QString &, const QMap< uint,QString > &))); + QObject::connect(object, SIGNAL(propertyChanged(const QString &, const QVariant &)), + parent(), SIGNAL(propertyChanged(const QString &, const QVariant &))); + QObject::connect(object, SIGNAL(disconnectRequested()), + parent(), SIGNAL(disconnectRequested())); + QObject::connect(object, SIGNAL(nodeCreated(const QString &)), + parent(), SIGNAL(nodeCreated(const QString &))); + QObject::connect(object, SIGNAL(nodeRemoved(const QString &)), + parent(), SIGNAL(nodeRemoved(const QString &))); + + + + } +} + +#include "bluetoothremotedevice.moc" diff --git a/solid/control/bluetoothremotedevice.h b/solid/control/bluetoothremotedevice.h new file mode 100644 index 000000000..c43b3ef5a --- /dev/null +++ b/solid/control/bluetoothremotedevice.h @@ -0,0 +1,165 @@ +/* This file is part of the KDE project + Copyright (C) 2007 Will Stephenson + Copyright (C) 2007 Daniel Gollub + Copyright (C) 2008 Tom Patzig + + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#ifndef SOLID_CONTROL_BLUETOOTHREMOTEDEVICE_H +#define SOLID_CONTROL_BLUETOOTHREMOTEDEVICE_H + +#include +#include +#include +#include + +#include "bluetoothmanager.h" +#include "bluetoothinterface.h" + +class KJob; + +namespace Solid +{ +namespace Control +{ +class BluetoothRemoteDevicePrivate; +/** + * Represents a bluetooth remote device as seen by the bluetoothing subsystem. + */ +class SOLIDCONTROL_EXPORT BluetoothRemoteDevice : public QObject +{ + Q_OBJECT + Q_DECLARE_PRIVATE(BluetoothRemoteDevice) + +public: + /** + * Creates a new BluetoothRemoteDevice object. + * + * @param backendObject the bluetooth remote device object provided by the backend + */ + BluetoothRemoteDevice(QObject *backendObject = 0); + + /** + * Constructs a copy of a bluetooth remote device. + * + * @param device the bluetooth remote device to copy + */ + BluetoothRemoteDevice(const BluetoothRemoteDevice &device); + + /** + * Destroys the device. + */ + ~BluetoothRemoteDevice(); + + /** + * Assigns a bluetooth remote device to this bluetooth remote device and returns a reference to it. + * + * @param device the bluetooth remote device to assign + * @return a reference to the bluetooth remote device + */ + BluetoothRemoteDevice &operator=(const BluetoothRemoteDevice &device); + + /** + * Checks for equality. + * @param other the bluetooth remote device to compare with this + * @return true if this->ubi() equals other.ubi(), false otherwise + */ + bool operator==(const BluetoothRemoteDevice & other) const; + + /** + * The UBI of the remote de device. + */ + QString ubi() const; + + /** + * Retrieve all properties from the remote device. + * + * @returns a hash of named properties + */ + QMap getProperties(); + + /** + * Discover all available Services from the remote Device. + * When the call is finished serviceDiscoverAvailable is thrown. + * + * @param pattern a service handle pattern to search for + */ + void discoverServices(const QString &pattern); + + /** + * List all defined Nodes. + * + * @returns a List of ObjectPaths from all defined Nodes + */ + QStringList listNodes(); + +public Q_SLOTS: + + /** + * Set a new Value for a named property. + * + * @param name the name of the property + * @param value the new value to be set + */ + void setProperty(const QString &name, const QVariant &value); + + /** + * Cancel a started service Discovery. + */ + void cancelDiscovery(); + + /** + * Request a disconnect from the remote device. + */ + void disconnect(); + +Q_SIGNALS: + + /** + * Search for services is done. + * + * @param status the result of the discovering. + * @param services the discovered Services. + */ + void serviceDiscoverAvailable(const QString &status, const QMap &services); + + /** + * A Property for the remote device has changed. + * + * @param name the name of the changed property + * @param value the new value + */ + void propertyChanged(const QString &name, const QVariant &value); + + /** + * Disconnect to the remote device requested. + */ + void disconnectRequested(); + + +protected: + BluetoothRemoteDevicePrivate *d_ptr; + +private: + Q_PRIVATE_SLOT(d_func(), void _k_destroyed(QObject *)) +}; + +} //Control +} //Solid + +#endif diff --git a/solid/control/bluetoothsecurity.cpp b/solid/control/bluetoothsecurity.cpp new file mode 100644 index 000000000..61c414e42 --- /dev/null +++ b/solid/control/bluetoothsecurity.cpp @@ -0,0 +1,139 @@ +/* This file is part of the KDE project + Copyright (C) 2006 Will Stephenson + Copyright (C) 2007 Daniel Gollub + Copyright (C) 2007 Juan González + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ +#include + +#include +#include +#include + +#include "ifaces/bluetoothsecurity.h" + +#include "soliddefs_p.h" + +#include "bluetoothmanager.h" +#include "bluetoothsecurity.h" +#include "bluetoothremotedevice.h" + +#include "frontendobject_p.h" +#include "managerbase_p.h" + +namespace Solid +{ +namespace Control +{ + class BluetoothSecurityPrivate: public FrontendObjectPrivate + { + public: + BluetoothSecurityPrivate(QObject *parent) + :FrontendObjectPrivate(parent){}; + QList registeredAgents; + }; +} //Control +} //Solid + +Solid::Control::BluetoothSecurity::BluetoothSecurity() + :QObject(0),d(new BluetoothSecurityPrivate(this)) +{ +} + +Solid::Control::BluetoothSecurity::BluetoothSecurity(QObject *backendObject) + :QObject(backendObject),d(new BluetoothSecurityPrivate(this)) +{ + d->setBackendObject(backendObject); +} + +Solid::Control::BluetoothSecurity::~BluetoothSecurity() +{ +} + +Solid::Control::BluetoothSecurity &Solid::Control::BluetoothSecurity::operator=(const Solid::Control::BluetoothSecurity & dev) +{ + if (dev.d) { + d->setBackendObject(dev.d->backendObject()); + } + //FIXME We are loosing the reference to the agents here... + return *this; +} + +void Solid::Control::BluetoothSecurity::setPasskeyAgent(Solid::Control::BluetoothPasskeyAgent * agent) +{ + SOLID_CALL(Solid::Control::Ifaces::BluetoothSecurity *,d->backendObject(),setPasskeyAgent(agent)) +} + +void Solid::Control::BluetoothSecurity::setAuthorizationAgent(Solid::Control::BluetoothAuthorizationAgent * agent) +{ + SOLID_CALL(Solid::Control::Ifaces::BluetoothSecurity *,d->backendObject(),setAuthorizationAgent(agent)) +} +/****************************** BluetoothPasskeyAgent implementation ******************************/ +Solid::Control::BluetoothPasskeyAgent::BluetoothPasskeyAgent(QObject * parent,const QString &interface) + :QObject(parent) +{ + //TODO Auto register all subclasses on BluetoothSecurity? +} + +QString Solid::Control::BluetoothPasskeyAgent::remote() +{ + return m_remote; +} + +QString Solid::Control::BluetoothPasskeyAgent::requestPasskey(const QString & ubi, bool isNumeric) +{ + Q_UNUSED(ubi) + Q_UNUSED(isNumeric) + return ""; +} + +bool Solid::Control::BluetoothPasskeyAgent::confirmPasskey(const QString & ubi, const QString & passkey) +{ + Q_UNUSED(ubi) + Q_UNUSED(passkey) + return false; +} + +void Solid::Control::BluetoothPasskeyAgent::displayPasskey(const QString & ubi, const QString & passkey) +{ + Q_UNUSED(ubi) + Q_UNUSED(passkey) +} + +void Solid::Control::BluetoothPasskeyAgent::keypress(const QString & ubi) +{ + Q_UNUSED(ubi) +} + +void Solid::Control::BluetoothPasskeyAgent::completedAuthentication(const QString & ubi) +{ + Q_UNUSED(ubi) +} + +void Solid::Control::BluetoothPasskeyAgent::cancelAuthentication(const QString & ubi) +{ + Q_UNUSED(ubi) +} +/****************************** BluetoothAuthorizationAgent implementation ******************************/ + +Solid::Control::BluetoothAuthorizationAgent::BluetoothAuthorizationAgent(QObject * parent) + :QObject(parent) +{ + +} + +#include "bluetoothsecurity.moc" diff --git a/solid/control/bluetoothsecurity.h b/solid/control/bluetoothsecurity.h new file mode 100644 index 000000000..f1a1e2749 --- /dev/null +++ b/solid/control/bluetoothsecurity.h @@ -0,0 +1,184 @@ +/* This file is part of the KDE project + Copyright (C) 2006 Will Stephenson + Copyright (C) 2007 Daniel Gollub + Copyright (C) 2007 Juan González + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#ifndef SOLID_CONTROL_BLUETOOTHSECURITY_H +#define SOLID_CONTROL_BLUETOOTHSECURITY_H + +#include +#include + +#include "singletondefs.h" +#include "solid_control_export.h" + +namespace Solid +{ +namespace Control +{ + /** + * This is the interface a class must implement to act as a Passkey Agent. + * A class that acts as a PassKeyAgent will handle the process of pairing + * (stablish a trusted connection) with a remote device. + */ + class SOLIDCONTROL_EXPORT BluetoothPasskeyAgent : public QObject + { + Q_OBJECT + Q_PROPERTY(QString remote READ remote) + public: + /** + * Initializes the passkey agent + * @param parent pointer to the parent object for auto deletion + * @param remote address of the remote device for this agent in 00:00:00:00:00:00 format. If empty the agent will act as the default passkey agent for all devices. + */ + BluetoothPasskeyAgent(QObject *parent = 0,const QString &remote=""); + //FIXME This method shouldn't be virtual, but the linker complains (and halts) if it isn't + /** + * Gets the UBI of the remote device this agent authenticates. + * @return Universal Bluetooth Identifier of the associated agent. If empty the agent authenticates any remote device that requires it. + */ + virtual QString remote(); + public Q_SLOTS: + /** + * This method gets called when the bluetooth system needs to get the passkey for a remote authentication. + * @param ubi Universal Bluetooth Identifier of the remote device + * @param isNumeric Indicates whether a numerical passkey is expected. + * @return The passkey to be used in this authentication, or an empty string if the request has been rejected/canceled + */ + virtual QString requestPasskey(const QString &ubi, bool isNumeric); + /** + * This method gets called when the bluetooth system needs to verify a passkey. The verification is + * done by showing the value to the passkey agent. + * @param ubi Universal Bluetooth Identifier of the remote device + * @param passkey The passkey to confirm. + * @return Whether the passkey accepts or not the remote passkey + */ + virtual bool confirmPasskey(const QString &ubi, const QString &passkey); + /** + * Gets called when the bluetooth system needs to show a passkey. No answer is + * expected from the agent. + * @param ubi Universal Bluetooth Identifier of the remote device + * @param passkey The passkey to show + */ + virtual void displayPasskey(const QString &ubi, const QString &passkey); + /** + * Indicates keypresses from a remote device,this can happen, for example, when pairing with a keyboard. + * @param ubi Universal Bluetooth Identifier of the remote device that emitted the keypress + */ + virtual void keypress(const QString &ubi); + /** + * Indicates to the agent that the authentication has been completed. + * @param ubi Universal Bluetooth Identifier of the remote device that has been authenticated + */ + virtual void completedAuthentication(const QString &ubi); + /** + * Indicates to the agent that the authentication has been canceled before completion. + * @param ubi Universal Bluetooth Identifier of the remote device which authentication was + */ + virtual void cancelAuthentication(const QString &ubi); + private: + /// UBI of the remote device this passkey agent handles authentication for. + QString m_remote; + }; + + /** + * This is the interface a class must implement to act as an Authorization Agent. + * An Authorization Agent handles requests to access local services from a remote + * device. + */ + class SOLIDCONTROL_EXPORT BluetoothAuthorizationAgent: public QObject + { + Q_OBJECT + public: + /** + * Used to keep the QObject deletion chain working. + * @param parent The parent of this object that will take care of deletion. + */ + BluetoothAuthorizationAgent(QObject *parent); + public Q_SLOTS: + /** + * This method gets called when the bluetooth system wants to get an authorization for accessing a local service. + * @param localUbi Universal Bluetooth Identifier of the local device providing the service + * @param remoteAddress of the remote device that wants to use our services + * @param serviceUuid Universal unique identifier for the local service + * @return whether the remote device is authorized to use the local service. + */ + virtual bool authorize(const QString &localUbi,const QString &remoteAddress,const QString& serviceUuid)=0; + /** + * Cancels the currently active authorization request for the given local/remote device. + * @param localUbi Universal Bluetooth Identifier of the local device providing the service + * @param remoteAddress of the remote device that wanted to use our services but canceled before completion. + * @param serviceUuid Universal unique identifier for the local service + */ + virtual void cancel(const QString &localUbi,const QString &remoteAddress,const QString& serviceUuid)=0; + }; + + class BluetoothSecurityPrivate; + /** + * Represents a bluetooth security interface which handles passkey request by the backend. + * To get an instance of this class use Solid::Control::BluetoothManager::security(). + */ + class SOLIDCONTROL_EXPORT BluetoothSecurity : public QObject + { + Q_OBJECT + public: + /** + * Constructs an invalid bluetooth security object + */ + BluetoothSecurity(); + + /** + * Constructs a new bluetooth security object taking its data from a backend. + * + * @param backendObject the object given by the backend + */ + explicit BluetoothSecurity(QObject *backendObject); + + /** + * Destroys the device. + */ + ~BluetoothSecurity(); + + /** + * Assigns a bluetooth security object to this bluetooth security object and returns a reference to it. + * + * @param device the bluetooth security object to assign + * @return a reference to the bluetooth security object + */ + BluetoothSecurity &operator=(const BluetoothSecurity &object); + public Q_SLOTS: + /** + * Sets the passkeyagent that will handle authentication (for pairing) requests in this process + * @param agent The PasskeyAgent for this process. If there is a previously registered agent it WON'T be deleted, track/parent your objects. + */ + void setPasskeyAgent(Solid::Control::BluetoothPasskeyAgent *agent); + /** + * Sets the authorizationagent that will handle service usage authorization requests in this process. + * @param agent The AuthorizationAgent for this process.If there is a previously registered agent it WON'T be deleted, track/parent your objects. + */ + void setAuthorizationAgent(Solid::Control::BluetoothAuthorizationAgent *agent); + private: + Q_PRIVATE_SLOT(d, void _k_destroyed(QObject *)) + + BluetoothSecurityPrivate * const d; + }; +} //Control +} //Solid + +#endif diff --git a/solid/control/frontendobject.cpp b/solid/control/frontendobject.cpp new file mode 100644 index 000000000..dfd995920 --- /dev/null +++ b/solid/control/frontendobject.cpp @@ -0,0 +1,65 @@ +/* This file is part of the KDE project + Copyright (C) 2006-2007 Kevin Ottens + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#include "frontendobject_p.h" + +#include + +Solid::Control::FrontendObjectPrivate::FrontendObjectPrivate(QObject *parent) + : m_parent(parent), m_backendObject(0) +{ +} + +Solid::Control::FrontendObjectPrivate::~FrontendObjectPrivate() +{ +} + +QObject *Solid::Control::FrontendObjectPrivate::parent() const +{ + return m_parent; +} + +QObject *Solid::Control::FrontendObjectPrivate::backendObject() const +{ + return m_backendObject; +} + +void Solid::Control::FrontendObjectPrivate::setBackendObject(QObject *object) +{ + if (m_backendObject) + { + QObject::disconnect(m_parent, 0, m_backendObject, 0); + m_backendObject->disconnect(m_parent); + } + + m_backendObject = object; + + if (m_backendObject) + { + QObject::connect(m_backendObject, SIGNAL(destroyed(QObject *)), + m_parent, SLOT(_k_destroyed(QObject *))); + } +} + +void Solid::Control::FrontendObjectPrivate::_k_destroyed(QObject *object) +{ + if (m_backendObject == object) { + m_backendObject = 0; + } +} diff --git a/solid/control/frontendobject_p.h b/solid/control/frontendobject_p.h new file mode 100644 index 000000000..4ab6da5be --- /dev/null +++ b/solid/control/frontendobject_p.h @@ -0,0 +1,49 @@ +/* This file is part of the KDE project + Copyright (C) 2006-2007 Kevin Ottens + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#ifndef SOLID_FRONTENDOBJECT_P_H +#define SOLID_FRONTENDOBJECT_P_H + +class QObject; + +namespace Solid +{ +namespace Control +{ + class FrontendObjectPrivate + { + public: + FrontendObjectPrivate(QObject *parent); + virtual ~FrontendObjectPrivate(); + + QObject *parent() const; + + QObject *backendObject() const; + virtual void setBackendObject(QObject *object); + + virtual void _k_destroyed(QObject *object); + + private: + QObject *m_parent; + QObject *m_backendObject; + }; +} +} + +#endif diff --git a/solid/control/ifaces/CMakeLists.txt b/solid/control/ifaces/CMakeLists.txt new file mode 100644 index 000000000..e85400d96 --- /dev/null +++ b/solid/control/ifaces/CMakeLists.txt @@ -0,0 +1,40 @@ + + +########### next target ############### + +set(solidcontrolifaces_LIB_SRCS + powermanager.cpp + networkinterface.cpp + networkcdmainterface.cpp + networkgsminterface.cpp + networkserialinterface.cpp + networkmanager.cpp + wirednetworkinterface.cpp + wirelessaccesspoint.cpp + wirelessnetworkinterface.cpp + bluetoothremotedevice.cpp + bluetoothinputdevice.cpp + bluetoothinterface.cpp + bluetoothmanager.cpp + bluetoothsecurity.cpp ) + +set(unused + networkmanager.cpp + network.cpp + wirelessnetwork.cpp + authentication.cpp + + ) + +kde4_add_library(solidcontrolifaces SHARED ${solidcontrolifaces_LIB_SRCS}) + +target_link_libraries(solidcontrolifaces ${KDE4_KDECORE_LIBS} ) + +set_target_properties(solidcontrolifaces PROPERTIES VERSION ${GENERIC_LIB_VERSION} SOVERSION ${GENERIC_LIB_SOVERSION} ) +install(TARGETS solidcontrolifaces ${INSTALL_TARGETS_DEFAULT_ARGS} ) + + +########### install files ############### + +install( FILES powermanager.h networkmanager.h networkinterface.h networkcdmainterface.h networkgsminterface.h networkserialinterface.h wirednetworkinterface.h wirelessnetworkinterface.h wirelessaccesspoint.h bluetoothremotedevice.h bluetoothinputdevice.h bluetoothinterface.h bluetoothmanager.h DESTINATION ${INCLUDE_INSTALL_DIR}/solid/control/ifaces COMPONENT Devel) + diff --git a/solid/control/ifaces/authentication.cpp b/solid/control/ifaces/authentication.cpp new file mode 100644 index 000000000..0cc8614d0 --- /dev/null +++ b/solid/control/ifaces/authentication.cpp @@ -0,0 +1,27 @@ +/* This file is part of the KDE project + Copyright (C) 2006,2007 Will Stephenson + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#include "authentication.h" + + +/******************************************************************************/ + +Solid::Control::Ifaces::AuthenticationValidator::~AuthenticationValidator() +{ +} diff --git a/solid/control/ifaces/authentication.h b/solid/control/ifaces/authentication.h new file mode 100644 index 000000000..d010036bf --- /dev/null +++ b/solid/control/ifaces/authentication.h @@ -0,0 +1,58 @@ +/* This file is part of the KDE project + Copyright (C) 2006,2007 Will Stephenson + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#ifndef SOLID_IFACES_AUTHENTICATION_H +#define SOLID_IFACES_AUTHENTICATION_H + +#include +#include +#include + +#include + +namespace Solid +{ +namespace Control +{ + class Authentication; + +namespace Ifaces +{ + /** + * Utility interface + * Specifies a backend specific validator class to validate authentication + * Can be used for example to authenticate user input as they type + */ + class SOLIDCONTROLIFACES_EXPORT AuthenticationValidator + { + public: + virtual ~AuthenticationValidator(); + /** + * Call this to check if an authentication is valid + * (All secrets present, passphrase length correct + */ + virtual bool validate(const Authentication *) = 0; + }; +} // Ifaces +} // Control +} // Solid + +Q_DECLARE_INTERFACE(Solid::Control::Ifaces::AuthenticationValidator, "org.kde.Solid.Control.Ifaces.AuthenticationValidator/0.1") + +#endif /* SOLID_IFACES_AUTHENTICATION_H */ diff --git a/solid/control/ifaces/bluetoothinputdevice.cpp b/solid/control/ifaces/bluetoothinputdevice.cpp new file mode 100644 index 000000000..c008acdd6 --- /dev/null +++ b/solid/control/ifaces/bluetoothinputdevice.cpp @@ -0,0 +1,30 @@ +/* This file is part of the KDE project + Copyright (C) 2007 Will Stephenson + Copyright (C) 2007 Daniel Gollub + + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#include "bluetoothinputdevice.h" + +Solid::Control::Ifaces::BluetoothInputDevice::BluetoothInputDevice(QObject * parent) : QObject(parent) +{} + +Solid::Control::Ifaces::BluetoothInputDevice::~BluetoothInputDevice() +{} + +#include "bluetoothinputdevice.moc" diff --git a/solid/control/ifaces/bluetoothinputdevice.h b/solid/control/ifaces/bluetoothinputdevice.h new file mode 100644 index 000000000..d6013c64e --- /dev/null +++ b/solid/control/ifaces/bluetoothinputdevice.h @@ -0,0 +1,100 @@ +/* This file is part of the KDE project + Copyright (C) 2007 Will Stephenson + Copyright (C) 2007 Daniel Gollub + + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#ifndef SOLID_IFACES_BLUETOOTHINPUTDEVICE +#define SOLID_IFACES_BLUETOOTHINPUTDEVICE + +#include +#include +#include + +#include "../solid_control_export.h" + +namespace Solid +{ +namespace Control +{ +namespace Ifaces +{ +/** + * A BluetoothInputDevice object allows to manage the connection of a bluetooth input device. + */ +class SOLIDCONTROLIFACES_EXPORT BluetoothInputDevice : public QObject +{ + Q_OBJECT +public: + /** + * Constructs a BluetoothInputDevice. + * + * @param parent the parent object + */ + BluetoothInputDevice(QObject * parent = 0); + + /** + * Destructs a BluetoothInputDevice object. + */ + virtual ~BluetoothInputDevice(); + + /** + * Retrieves ubi of bluetooth input device. + * + * @returns ubi of bluetooth input device + */ + virtual QString ubi() const = 0; + /** + * Retrieve all properties from the input device. + * + * @returns a hash of named properties + */ + virtual QMap getProperties() const = 0; + + +public Q_SLOTS: + /** + * Connect bluetooth input device. + */ + virtual void connect() = 0; + + /** + * Disconnect bluetooth input device. + */ + virtual void disconnect() = 0; + +Q_SIGNALS: + /** + * A Property for the input device has changed. + * + * @param name the name of the changed property + * @param value the new value + */ + virtual void propertyChanged(const QString &name, const QVariant &value) = 0; + +}; + +} // Ifaces + +} // Control + +} // Solid + +Q_DECLARE_INTERFACE(Solid::Control::Ifaces::BluetoothInputDevice, "org.kde.Solid.Control.Ifaces.BluetoothInputDevice/0.1") + +#endif diff --git a/solid/control/ifaces/bluetoothinterface.cpp b/solid/control/ifaces/bluetoothinterface.cpp new file mode 100644 index 000000000..3e77c833e --- /dev/null +++ b/solid/control/ifaces/bluetoothinterface.cpp @@ -0,0 +1,31 @@ +/* This file is part of the KDE project + Copyright (C) 2006 Will Stephenson + Copyright (C) 2007 Daniel Gollub + + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#include "bluetoothinterface.h" + +Solid::Control::Ifaces::BluetoothInterface::BluetoothInterface(QObject *parent) + : QObject(parent) +{} + +Solid::Control::Ifaces::BluetoothInterface::~BluetoothInterface() +{} + +#include "bluetoothinterface.moc" diff --git a/solid/control/ifaces/bluetoothinterface.h b/solid/control/ifaces/bluetoothinterface.h new file mode 100644 index 000000000..e23bbb00d --- /dev/null +++ b/solid/control/ifaces/bluetoothinterface.h @@ -0,0 +1,517 @@ +/* This file is part of the KDE project + Copyright (C) 2007 Will Stephenson + Copyright (C) 2007 Daniel Gollub + + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#ifndef SOLID_IFACES_BLUETOOTHINTERFACE_H +#define SOLID_IFACES_BLUETOOTHINTERFACE_H + +#include +#include "../solid_control_export.h" + +#include "../bluetoothinterface.h" +#include "bluetoothremotedevice.h" + +#include + +namespace Solid +{ +namespace Control +{ +namespace Ifaces +{ +/** + * Represents a bluetooth interface as seen by the bluetooth subsystem. + */ +class SOLIDCONTROLIFACES_EXPORT BluetoothInterface : public QObject +{ + Q_OBJECT +public: + /** + * Create a BluetoothInterface. + * + * @param parent the parent object + */ + BluetoothInterface(QObject *parent = 0); + + /** + * Destructs a BluetoothInterface object. + */ + virtual ~BluetoothInterface(); + + /** + * Retrieves the Universal Bluetooth Identifier (UBI) of the BluetoothInterface. + * This identifier is unique for each bluetooth remote device and bluetooth interface in the system. + * + * @returns the Universal Bluetooth Identifier of the current bluetooth interface + */ + virtual QString ubi() const = 0; + + /** + * Retrieves the MAC address of the bluetooth interface/adapter. + * + * @returns MAC address of bluetooth interface + */ + //virtual QString address() const = 0; + + /** + * Retrieves the version of the chip of the bluetooth interface/adapter. + * Example: "Bluetooth 2.0 + EDR" + * + * @returns bluetooth chip version + */ + //virtual QString version() const = 0; + + /** + * Retrieves the revision of the chip of the bluetooth interface/adapter. + * Example: "HCI 19.2" + * + * @returns bluetooth chip revision + */ + //virtual QString revision() const = 0; + + /** + * Retrieves the name of the bluetooth chip manufacturer. + * Example: "Cambdirge Silicon Radio" + * + * @returns manufacturer string of bluetooth interface/adapter + */ + //virtual QString manufacturer() const = 0; + + /** + * Retrieves the name of the bluetooth chip company. + * Based on device address. + * + * @returns company string of bluetooth interface/adapter + */ + //virtual QString company() const = 0; + + + /** + * Retrieves the current mode of the bluetooth interface/adapter. + * Valid modes: "off", "connectable", "discoverable" + * + * @todo determine unify type for valid modes.. enum?! what about other bluetooth APIs? + * three modes? + * + * @returns current mode of bluetooth interface/adaoter + */ + //virtual Solid::Control::BluetoothInterface::Mode mode() const = 0; + + /** + * Retrieves the discoverable timeout of the bluetooth interface/adapter. + * Discoverable timeout of 0 means never disappear. + * + * @returns current discoverable timeout in seconds + */ + //virtual int discoverableTimeout() const = 0; + + /** + * Retrieves the current discoverable staut of the bluetooth interface/adapter. + * + * @returns current discoverable status of bluetooth interface/adapter + */ + //virtual bool isDiscoverable() const = 0; + + + /** + * List all UBIs of connected remote bluetooth devices of this handled bluetooth + * interface/adapter. + * + * @returns list UBIs of connected bluetooth remote devices + */ + //virtual QStringList listConnections() const = 0; + + + /** + * Retrieves major class of the bluetooth interface/adapter. + * + * @returns current major class of the bluetooth interface/adapter + */ + //virtual QString majorClass() const = 0; + + /** + * List supported minor classes of the bluetooth interface/adapter. + * + * @returns list of supported minor classes by bluetooth interface/adapter + */ + //virtual QStringList listAvailableMinorClasses() const = 0; + + /** + * Retrievies minor class of the bluetooth interface/adapter. + * Valid classes, see listAvailableMinorClasses() + * + * @returns minor class of the bluetooth interface/adapter. + */ + //virtual QString minorClass() const = 0; + + /** + * List services class of the bluetooth interface/adapter. + * + * @returns list of service classes or empty list if no services registered + */ + //virtual QStringList serviceClasses() const = 0; + /** + * Retrieves name of bluetooth interface/adapter. + * + * @returns name of bluetooth interface/adapter + */ + //virtual QString name() const = 0; + + /** + * Returns the name of the remote device, given its mac address (mac). + * + * @return the name of the remote device + */ + //virtual QString getRemoteName(const QString & mac) = 0; + + /** + * List UBIs of bonded/paired remote bluetooth devices with this bluetooth + * interface/adapter. + * + * @returns UBIs of bonded/paired bluetooth remote devices + */ + //virtual QStringList listBondings() const = 0; + + /** + * Periodic discovery status of this bluetooth interface/adapter. + * + * @returns true if periodic discovery is already active otherwise false + */ + //virtual bool isPeriodicDiscoveryActive() const = 0; + + /** + * Name resolving status of periodic discovery routing. + * + * @returns true if name got resolved while periodic discovery of this bluetooth + * interface/adapter + */ + //virtual bool isPeriodicDiscoveryNameResolvingActive() const = 0; + + /** + * List the Universal Bluetooth Identifier (UBI) of all known remote devices, which are + * seen, used or paired/bonded. + * + * See listConnections() + * + * @returns a QStringList of UBIs of all known remote bluetooth devices + */ + //virtual QStringList listRemoteDevices() const = 0; + + /** + * List the Universal Bluetooth Identifier (UBI) of all known remote devices since a specific + * datestamp. Known remote devices means remote bluetooth which are seen, used or + * paired/bonded. + * + * See listConnections(), listRemoteDevices() + * + * @param date the datestamp of the beginning of recent used devices + * @returns a QStringList of UBIs of all known remote bluetooth devices + */ + // virtual QStringList listRecentRemoteDevices(const QDateTime &date) const = 0; + + /** + * Returns true if the remote bluetooth device is trusted otherwise false. + * + * @param mac the address of the remote device + */ +// virtual bool isTrusted(const QString &) = 0; + + /** + * + * + * + */ + + + virtual QString createPairedDevice(const QString &, const QString &, const QString &) const = 0; + + virtual QMap< QString, QVariant > getProperties() const = 0; + + virtual QStringList listDevices() const = 0; + + virtual QString findDevice(const QString &) const = 0; + + virtual QString createDevice(const QString &) const = 0; + + + +//public Q_SLOTS: + /** + * Set mode of bluetooth interface/adapter. + * Valid modes, see mode() + * + * @param mode the mode of the bluetooth interface/adapter + */ + //virtual void setMode(const Solid::Control::BluetoothInterface::Mode mode) = 0; + + /** + * Set discoverable timeout of bluetooth interface/adapter. + * + * @param timeout timeout in seconds + */ + //virtual void setDiscoverableTimeout(int timeout) = 0; + + /** + * Set minor class of bluetooth interface/adapter. + * + * @param minor set minor class. Valid mode see listAvaliableMinorClasses() + */ + //virtual void setMinorClass(const QString &minor) = 0; + + /** + * Set name of bluetooth interface/adapter. + * + * @param name the name of bluetooth interface/adapter + */ + //virtual void setName(const QString &name) = 0; + + + /** + * Start discovery of remote bluetooth devices with device name resolving. + */ + //virtual void discoverDevices() = 0; + /** + * Start discovery of remote bluetooth devices without device name resolving. + */ + //virtual void discoverDevicesWithoutNameResolving() = 0; + /** + * Cancel discovery of remote bluetooth devices. + */ + //virtual void cancelDiscovery() = 0; + + /** + * Start periodic discovery of remote bluetooth devices. + * See stopPeriodicDiscovery() + */ + //virtual void startPeriodicDiscovery() = 0; + + /** + * Stop periodic discovery of remote bluetooth devices. + */ + //virtual void stopPeriodicDiscovery() = 0; + + /** + * Enable/Disable name resolving of remote bluetooth devices in periodic discovery. + * + * @param resolveName true to enable name resolving otherwise false + */ + //virtual void setPeriodicDiscoveryNameResolving(bool resolveNames) = 0; + + /** + * Instantiates a new BluetoothRemoteDevice object from this backend given its address. + * + * @param ubi the identifier of the bluetooth remote device instantiated + * @returns a new BluetoothRemoteDevice object if there's a device having the given UBI, 0 otherwise + */ + virtual QObject *createBluetoothRemoteDevice(const QString &address) = 0; + + /** + * Marks the device as trusted. + * + * @param mac the address of the remote device + */ + //virtual void setTrusted(const QString &) = 0; + + /** + * Marks the device as not trusted. + * + * @param mac the address of the remote device + */ + //virtual void removeTrust(const QString &) = 0; + + virtual void registerAgent(const QString &,const QString &) = 0; + + virtual void releaseSession() = 0; + + virtual void removeDevice(const QString &) = 0; + + virtual void requestSession() = 0; + + virtual void setProperty(const QString &, const QVariant &) = 0; + + virtual void startDiscovery() = 0; + + virtual void stopDiscovery() = 0; + + virtual void unregisterAgent(const QString &) = 0; + + virtual void cancelDeviceCreation(const QString &) = 0; + + +Q_SIGNALS: + + /** + * This signal is emitted if the mode of the bluetooth interface/adapter has changed. + * See mode() for valid modes. + * + * @param mode the changed mode + */ + //void modeChanged(Solid::Control::BluetoothInterface::Mode); + + /** + * The signal is emitted if the discoverable timeout of the bluetooth interface/adapter + * has changed. + * + * @param timeout the changed timeout in seconds + */ + //void discoverableTimeoutChanged(int timeout); + + /** + * The signal is emitted if the minor class of the bluetooth interface/adapter has changed. + * + * @param minor the new minor class + */ + //void minorClassChanged(const QString &minor); + + /** + * The signal is emitted if the name of the bluetooth interface/adapter has changed. + * + * @param name the new name of the device + */ + //void nameChanged(const QString &name); + + /** + * This signal is emitted if a discovery has started. + */ + //void discoveryStarted(); + + /** + * This signal is emitted if a discovery has completed. + */ + //void discoveryCompleted(); + + /** + * This signal is emitted if the bluetooth interface/adapter detects a new remote bluetooth device. + * + * @todo change arguments types of deviceClass (uint32) and rssi (int16) + * + * @param ubi the new bluetooth identifier + * @param deviceClass the device Class of the remote device + * @param rssi the RSSI link of the remote device + */ + //void remoteDeviceFound(const QString &ubi, int deviceClass, int rssi); + + /** + * This signal is emitted if the bluetooth interface/adapter detectes a bluetooth device + * disappeared. + * + * @param ubi the ubi of the disappering bluetooth remote device + */ + //void remoteDeviceDisappeared(const QString &ubi); + + /** + * This signal is emitted if the bluetooth interface/adapter detectes a new name for a + * bluetooth device. + * + * @param address the address of the bluetooth remote device + * @param name the name of the bluetooth remote device + */ + //void remoteNameUpdated(const QString &address, const QString &name); + + /** + * This signal is emitted if a bluetooth connection has been created. + * + * @param address the address of the connected bluetooth remote device + */ + //void remoteDeviceConnected(const QString &address); + + /** + * This signal is emitted if a bluetooth connection has been terminated. + * + * @param address the address of the disconnected bluetooth remote device + */ + //void remoteDeviceDisconnected(const QString &address); + + /** + * This signal is emitted if a bluetooth device was set trusted. + * + * @param address the address of the trusted bluetooth remote device + */ + //void trustAdded(const QString &address); + + /** + * This signal is emitted if the trust to the bluetooth device was removed. + * + * @param address the address of the bluetooth remote device + */ + //void trustRemoved(const QString &address); + + /** + * This signal is emitted if a successful bonding has been created. + * + * @param address the address of the bluetooth remote device + */ + //void bondingCreated(const QString &address); + + /** + * This signal is emitted if the bonding to a bluetooth device has been removed. + * + * @param address the address of the bluetooth remote device + */ + //void bondingRemoved(const QString &address); + + /** + * This signal is emitted when a remote device is created. + * + * @param ubi the object path of the device on the system bus + */ + void deviceCreated(const QString &ubi); + + /** + * This signal is emitted when an inquiry session for a periodic discovery finishes and previously found + * devices are no longer in range or visible. + * + * @param address the address of the remote device + */ + void deviceDisappeared(const QString &address); + + /** + * This signal will be emitted every time an inquiry result has been found by the service daemon. + * In general they only appear during a device discovery. + * + * @param address the address of the remote device + * @param properties the properties of the remote device + */ + void deviceFound(const QString &address, const QMap< QString,QVariant > &properties); + + /** + * This signal is emitted when a remote device is removed from the system bus. + * + * @param ubi the object path on the system bus from the remote device + */ + void deviceRemoved(const QString &ubi); + + /** + * This signal is emitted when a property of the adapter is set to a new value. + * + * @param property the named property of the adapter + * @value the new value for the property + */ + void propertyChanged(const QString &property, const QVariant &value); + + +}; +} //Ifaces +} //Control +} //Solid + +Q_DECLARE_INTERFACE(Solid::Control::Ifaces::BluetoothInterface, "org.kde.Solid.Control.Ifaces.BluetoothInterface/0.1") + +#endif diff --git a/solid/control/ifaces/bluetoothmanager.cpp b/solid/control/ifaces/bluetoothmanager.cpp new file mode 100644 index 000000000..fd0e493bd --- /dev/null +++ b/solid/control/ifaces/bluetoothmanager.cpp @@ -0,0 +1,31 @@ +/* This file is part of the KDE project + Copyright (C) 2007 Will Stephenson + Copyright (C) 2007 Daniel Gollub + + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#include "bluetoothmanager.h" +#include "bluetoothsecurity.h" + +Solid::Control::Ifaces::BluetoothManager::BluetoothManager(QObject * parent) : QObject(parent) +{} + +Solid::Control::Ifaces::BluetoothManager::~BluetoothManager() +{} + +#include "bluetoothmanager.moc" diff --git a/solid/control/ifaces/bluetoothmanager.h b/solid/control/ifaces/bluetoothmanager.h new file mode 100644 index 000000000..6df079016 --- /dev/null +++ b/solid/control/ifaces/bluetoothmanager.h @@ -0,0 +1,172 @@ +/* This file is part of the KDE project + Copyright (C) 2007 Will Stephenson + Copyright (C) 2007 Daniel Gollub + + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#ifndef SOLID_IFACES_BLUETOOTHMANAGER +#define SOLID_IFACES_BLUETOOTHMANAGER + +#include +#include "../solid_control_export.h" + +class KJob; + +namespace Solid +{ +namespace Control +{ +namespace Ifaces +{ +class BluetoothSecurity; +/** + * This class specifies the interface a backend will have to implement in + * order to be used in the system. + * + * A bluetooth manager allow to query the underlying platform to discover the + * available bluetooth interfaces. + */ +class SOLIDCONTROLIFACES_EXPORT BluetoothManager : public QObject +{ + Q_OBJECT +public: + /** + * Constructs a BluetoothManager. + * + * @param parent the parent object + */ + BluetoothManager(QObject * parent = 0); + /** + * Destructs a BluetoothManager object. + */ + virtual ~BluetoothManager(); + + /** + * Retrieves the list of all the bluetooth interfaces Universal Bluetooth Identifiers (UBIs) + * in the system. + * + * @return the list of bluetooth interfaces available in this system + */ + virtual QStringList bluetoothInterfaces() const = 0; + + /** + * Retrieves the default bluetooth interface Universal Bluetooth Identifiers (UBIs) + * of the system. + * + * @return the UBI of the default bluetooth interface + */ + virtual QString defaultInterface() const = 0; + + /** + * Returns the UBI of the Bluetooth Interface given its name (e.g. 'hci0'), + * if found on the system. + * + * @return the found UBI of the named bluetooth interface + */ + virtual QString findInterface(const QString &name) const = 0; + + /** + * Instantiates a new BluetoothInterface object from this backend given its UBI. + * + * @param ubi the identifier of the bluetooth interface instantiated + * @returns a new BluetoothInterface object if there's a device having the given UBI, 0 otherwise + */ + virtual QObject *createInterface(const QString &ubi) = 0; + + /** + * Retrieves the list of Universal Bluetooth Identifiers (UBIs) of bluetooth input devices + * which are configured in the system. Configured means also not connected devices. + * + * @return the list of bluetooth input devices configured in this system + */ +// virtual QStringList bluetoothInputDevices() const = 0; + + /** + * Instantiates a new BluetoothInputDevice object from this backend given its UBI. + * + * @param ubi the identifier of the bluetooth input device instantiated + * @returns a new BluetoothInputDevice object if there's a device having the given UBI, 0 otherwise + */ +// virtual QObject *createBluetoothInputDevice(const QString &ubi) = 0; + + /** + * Setup a new bluetooth input device. + * + * @param ubi the ubi of the bluetooth input device + * @returns job handling of the operation. + */ +// virtual KJob *setupInputDevice(const QString &ubi) = 0; + + /** + * Gets an instance of BluetoothSecurity to handle pairing/authorization requests + */ +// virtual Solid::Control::Ifaces::BluetoothSecurity* security(const QString &interface) = 0; + +public Q_SLOTS: + /** + * Remove the configuraiton of a bluetooth input device. + * + * @param ubi the bluetooth input device identifier + */ +// virtual void removeInputDevice(const QString & ubi) = 0; + +Q_SIGNALS: + /** + * This signal is emitted when a new bluetooth interface is available. + * + * @param ubi the bluetooth interface identifier + */ + void interfaceAdded(const QString & ubi); + + /** + * This signal is emitted when a bluetooth interface is not available anymore. + * + * @param ubi the bluetooth interface identifier + */ + void interfaceRemoved(const QString & ubi); + + /** + * This signal is emitted when the default bluetooth interface changed. + * + * @param ubi the bluetooth interface identifier + */ + void defaultInterfaceChanged(const QString & ubi); + + /** + * This signal is emitted when a new bluetooth input device got configured/created. + * + * @param ubi the bluetooth input device identifier + */ +// void inputDeviceCreated(const QString & ubi); + + /** + * This signal is emitted when a bluetooth input device configuration is not available anymore. + * + * @param ubi the bluetooth input device identifier + */ +// void inputDeviceRemoved(const QString & ubi); + +}; + +} // Ifaces + +} // Control + +} // Solid + +#endif diff --git a/solid/control/ifaces/bluetoothremotedevice.cpp b/solid/control/ifaces/bluetoothremotedevice.cpp new file mode 100644 index 000000000..8ae46c3b6 --- /dev/null +++ b/solid/control/ifaces/bluetoothremotedevice.cpp @@ -0,0 +1,30 @@ +/* This file is part of the KDE project + Copyright (C) 2006 Will Stephenson + Copyright (C) 2007 Daniel Gollub + + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#include "bluetoothremotedevice.h" + +Solid::Control::Ifaces::BluetoothRemoteDevice::BluetoothRemoteDevice(QObject * parent) : QObject(parent) +{} + +Solid::Control::Ifaces::BluetoothRemoteDevice::~BluetoothRemoteDevice() +{} + +#include "bluetoothremotedevice.moc" diff --git a/solid/control/ifaces/bluetoothremotedevice.h b/solid/control/ifaces/bluetoothremotedevice.h new file mode 100644 index 000000000..61d251f8c --- /dev/null +++ b/solid/control/ifaces/bluetoothremotedevice.h @@ -0,0 +1,131 @@ +/* This file is part of the KDE project + Copyright (C) 2007 Will Stephenson + Copyright (C) 2007 Daniel Gollub + + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#ifndef SOLID_IFACES_BLUETOOTHREMOTEDEVICE +#define SOLID_IFACES_BLUETOOTHREMOTEDEVICE + +#include +#include +#include "../solid_control_export.h" + +class KJob; + +namespace Solid +{ +namespace Control +{ +namespace Ifaces +{ +/** + * This interface represents a remote bluetooth device which we may be connected to. + */ +class SOLIDCONTROLIFACES_EXPORT BluetoothRemoteDevice : public QObject +{ + Q_OBJECT +public: + /** + * Create a BluetoothRemoteDevice. + * + * @param parent the parent object + */ + BluetoothRemoteDevice(QObject *parent = 0); + + /** + * Destructs a BluetoothRemoteDevice object. + */ + virtual ~BluetoothRemoteDevice(); + /** + * Retrieve all properties from the remote device. + * + * @returns a hash of named properties + */ + virtual QMap getProperties() const = 0; + /** + * Discover all available Services from the remote Device. + * When the call is finished serviceDiscoverAvailable is thrown. + * + * @param pattern a service handle pattern to search for + */ + virtual void discoverServices(const QString &pattern) const = 0; + /** + * List all defined Nodes. + * + * @returns a List of ObjectPaths from all defined Nodes + */ + virtual QStringList listNodes() const = 0; + /** + * The UBI of the remote device. + */ + virtual QString ubi() const = 0; + + +public Q_SLOTS: + /** + * Set a new Value for a named property. + * + * @param name the name of the property + * @param value the new value to be set + */ + virtual void setProperty(const QString &name, const QVariant &value) = 0; + /** + * Cancel a started service Discovery. + */ + virtual void cancelDiscovery() = 0; + /** + * Request a disconnect from the remote device. + */ + virtual void disconnect() = 0; + + + +Q_SIGNALS: + /** + * Search for services is done. + * + * @param status the result of the discovering. + * @param services the discovered Services. + */ + virtual void serviceDiscoverAvailable(const QString &status, const QMap &services) = 0; + /** + * A Property for the remote device has changed. + * + * @param name the name of the changed property + * @param value the new value + */ + virtual void propertyChanged(const QString &name, const QVariant &value) = 0; + /** + * Disconnect to the remote device requested. + */ + virtual void disconnectRequested() = 0; + + + +}; + +} // Ifaces + +} // Control + +} // Solid + +Q_DECLARE_INTERFACE(Solid::Control::Ifaces::BluetoothRemoteDevice, "org.kde.Solid.Control.Ifaces.BluetoothRemoteDevice/0.1") + +#endif diff --git a/solid/control/ifaces/bluetoothsecurity.cpp b/solid/control/ifaces/bluetoothsecurity.cpp new file mode 100644 index 000000000..f426d5b60 --- /dev/null +++ b/solid/control/ifaces/bluetoothsecurity.cpp @@ -0,0 +1,38 @@ +/* This file is part of the KDE project + Copyright (C) 2006 Will Stephenson + Copyright (C) 2007 Daniel Gollub + Copyright (C) 2007 Juan González + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#include "bluetoothsecurity.h" + +Solid::Control::Ifaces::BluetoothSecurity::BluetoothSecurity(QObject *parent) + : QObject(parent) +{} + +Solid::Control::Ifaces::BluetoothSecurity::BluetoothSecurity(const QString & interface, QObject * parent) + : QObject(parent) +{ + Q_UNUSED(interface) +} + +Solid::Control::Ifaces::BluetoothSecurity::~BluetoothSecurity() +{} + + +#include "bluetoothsecurity.moc" diff --git a/solid/control/ifaces/bluetoothsecurity.h b/solid/control/ifaces/bluetoothsecurity.h new file mode 100644 index 000000000..3ede275a9 --- /dev/null +++ b/solid/control/ifaces/bluetoothsecurity.h @@ -0,0 +1,73 @@ +/* This file is part of the KDE project + Copyright (C) 2007 Will Stephenson + Copyright (C) 2007 Daniel Gollub + Copyright (C) 2007 Juan González + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#ifndef SOLID_IFACES_BLUETOOTHSECURITY_H +#define SOLID_IFACES_BLUETOOTHSECURITY_H + +#include "../solid_control_export.h" +#include "../bluetoothsecurity.h" // So we know about Solid::Control::BluetoothPassKeyAgent + +#include + +namespace Solid +{ +namespace Control +{ +namespace Ifaces +{ +/** + * Represents a bluetooth interface as seen by the bluetooth subsystem. + */ +class SOLIDCONTROLIFACES_EXPORT BluetoothSecurity : public QObject +{ + Q_OBJECT +public: + /** + * Create a BluetoothSecurity object for all Bluetooth Interfaces. + * + * @param parent the parent object + */ + BluetoothSecurity(QObject *parent = 0); + + /** + * Create a BluetoothSecurity object for a certain Bluetooth Interfaces. + * + * @param interface the ubi of a certain Bluetooth Interface + * @param parent the parent object + */ + BluetoothSecurity(const QString &interface, QObject *parent = 0); + + /** + * Destructs a BluetoothSecurity object. + */ + virtual ~BluetoothSecurity(); +public Q_SLOTS: + virtual void setPasskeyAgent(Solid::Control::BluetoothPasskeyAgent *agent) = 0; + virtual void setAuthorizationAgent(Solid::Control::BluetoothAuthorizationAgent *agent) = 0; +}; +} //Ifaces +} //Control +} //Solid + +Q_DECLARE_INTERFACE(Solid::Control::Ifaces::BluetoothSecurity, "org.kde.Solid.Ifaces.BluetoothSecurity/0.1") + +#endif + diff --git a/solid/control/ifaces/networkcdmainterface.cpp b/solid/control/ifaces/networkcdmainterface.cpp new file mode 100644 index 000000000..4927192f9 --- /dev/null +++ b/solid/control/ifaces/networkcdmainterface.cpp @@ -0,0 +1,27 @@ +/* +Copyright 2008 Will Stephenson + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) version 3, or any +later version accepted by the membership of KDE e.V. (or its +successor approved by the membership of KDE e.V.), which shall +act as a proxy defined in Section 6 of version 3 of the license. + +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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library. If not, see . +*/ +#include "networkcdmainterface.h" + +Solid::Control::Ifaces::CdmaNetworkInterface::~CdmaNetworkInterface() +{ + +} + +// vim: sw=4 sts=4 et tw=100 diff --git a/solid/control/ifaces/networkcdmainterface.h b/solid/control/ifaces/networkcdmainterface.h new file mode 100644 index 000000000..ab589aca5 --- /dev/null +++ b/solid/control/ifaces/networkcdmainterface.h @@ -0,0 +1,62 @@ +/* +Copyright 2008 Will Stephenson + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) version 3, or any +later version accepted by the membership of KDE e.V. (or its +successor approved by the membership of KDE e.V.), which shall +act as a proxy defined in Section 6 of version 3 of the license. + +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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library. If not, see . +*/ + +#ifndef SOLID_IFACES_CDMANETWORKINTERFACE_H +#define SOLID_IFACES_CDMANETWORKINTERFACE_H + +#include "../solid_control_export.h" + +#include + +#include "../networkcdmainterface.h" +#include "networkserialinterface.h" + + +namespace Solid +{ +namespace Control +{ +namespace Ifaces +{ + /** + * Represents a wireless network interface + */ + class SOLIDCONTROLIFACES_EXPORT CdmaNetworkInterface : virtual public SerialNetworkInterface + { + public: + /** + * Destroys a CdmaNetworkInterface object + */ + virtual ~CdmaNetworkInterface(); + /** + * List of wireless networks currently visible to the hardware + */ + + protected: + //Q_SIGNALS: + }; +} //Ifaces +} //Control +} //Solid + +Q_DECLARE_INTERFACE(Solid::Control::Ifaces::CdmaNetworkInterface, "org.kde.Solid.Control.Ifaces.CdmaNetworkInterface/0.1") + +#endif //SOLID_IFACES_CDMANETWORKINTERFACE_H + diff --git a/solid/control/ifaces/networkgsminterface.cpp b/solid/control/ifaces/networkgsminterface.cpp new file mode 100644 index 000000000..e9db3bdae --- /dev/null +++ b/solid/control/ifaces/networkgsminterface.cpp @@ -0,0 +1,27 @@ +/* +Copyright 2008 Will Stephenson + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) version 3, or any +later version accepted by the membership of KDE e.V. (or its +successor approved by the membership of KDE e.V.), which shall +act as a proxy defined in Section 6 of version 3 of the license. + +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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library. If not, see . +*/ +#include "networkgsminterface.h" + +Solid::Control::Ifaces::GsmNetworkInterface::~GsmNetworkInterface() +{ + +} + +// vim: sw=4 sts=4 et tw=100 diff --git a/solid/control/ifaces/networkgsminterface.h b/solid/control/ifaces/networkgsminterface.h new file mode 100644 index 000000000..007082d1e --- /dev/null +++ b/solid/control/ifaces/networkgsminterface.h @@ -0,0 +1,58 @@ +/* +Copyright 2008 Will Stephenson + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) version 3, or any +later version accepted by the membership of KDE e.V. (or its +successor approved by the membership of KDE e.V.), which shall +act as a proxy defined in Section 6 of version 3 of the license. + +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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library. If not, see . +*/ + +#ifndef SOLID_IFACES_GSMNETWORKINTERFACE_H +#define SOLID_IFACES_GSMNETWORKINTERFACE_H + +#include "../solid_control_export.h" + +#include + +#include "../networkgsminterface.h" +#include "networkserialinterface.h" + + +namespace Solid +{ +namespace Control +{ +namespace Ifaces +{ + /** + * Represents a wireless network interface + */ + class SOLIDCONTROLIFACES_EXPORT GsmNetworkInterface : virtual public SerialNetworkInterface + { + public: + /** + * Destroys a GsmNetworkInterface object + */ + virtual ~GsmNetworkInterface(); + protected: + //Q_SIGNALS: + }; +} //Ifaces +} //Control +} //Solid + +Q_DECLARE_INTERFACE(Solid::Control::Ifaces::GsmNetworkInterface, "org.kde.Solid.Control.Ifaces.GsmNetworkInterface/0.1") + +#endif //SOLID_IFACES_GSMNETWORKINTERFACE_H + diff --git a/solid/control/ifaces/networkinterface.cpp b/solid/control/ifaces/networkinterface.cpp new file mode 100644 index 000000000..e946056c6 --- /dev/null +++ b/solid/control/ifaces/networkinterface.cpp @@ -0,0 +1,26 @@ +/* This file is part of the KDE project + Copyright (C) 2006 Will Stephenson + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#include "networkinterface.h" + +Solid::Control::Ifaces::NetworkInterface::~NetworkInterface() +{ + +} + diff --git a/solid/control/ifaces/networkinterface.h b/solid/control/ifaces/networkinterface.h new file mode 100644 index 000000000..7885e36f3 --- /dev/null +++ b/solid/control/ifaces/networkinterface.h @@ -0,0 +1,123 @@ +/* This file is part of the KDE project + Copyright (C) 2006 Will Stephenson + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#ifndef SOLID_CONTROL_IFACES_NETWORKINTERFACE_H +#define SOLID_CONTROL_IFACES_NETWORKINTERFACE_H + +#include "../solid_control_export.h" +#include "../networkinterface.h" +#include +#include + +namespace Solid +{ +namespace Control +{ +namespace Ifaces +{ + /** + * Represents a generic network interface as seen by the networking subsystem. + * + * For specialized interfaces @see Solid::Control::Ifaces::WiredNetworkInterface and @see + * Solid::Control::Ifaces::WirelessNetworkInterface + */ + class SOLIDCONTROLIFACES_EXPORT NetworkInterface + { + public: + /** + * Destroys a NetworkInterface object. + */ + virtual ~NetworkInterface(); + + /** + * Retrieves the Unique Network Identifier (UNI) of the Network. + * This identifier is unique for each network and network interface in the system. + * + * @returns the Unique Network Identifier of the current network + */ + virtual QString uni() const = 0; + /** + * The system name for the network interface + */ + virtual QString interfaceName() const = 0; + + /** + * Handle for the system driver controlling this network interface + */ + virtual QString driver() const = 0; + + /** + * Access the network configuration for this object + */ + virtual Solid::Control::IPv4Config ipV4Config() const = 0; + + /** + * Retrieves the activation status of this network interface. + * + * @return true if this network interface is active, false otherwise + */ + virtual bool isActive() const = 0; + /** + * Retrieves the current state of the network connection held by this device. + * It's a high level view of the connection. It's user oriented so technically + * it provides states coming from different layers. + * + * @return the current connection state + * @see Solid::Control::NetworkInterface::ConnectionState + */ + virtual Solid::Control::NetworkInterface::ConnectionState connectionState() const = 0; + /** + * Retrieves the maximum speed as reported by the device. Note that it's a design + * related information and that the device might not reach this maximum. + * + * @return the device maximum speed + */ + virtual int designSpeed() const = 0; + + /** + * Retrieves the capabilities supported by this device. + * + * @return the capabilities of the device + * @see Solid::Control::NetworkInterface::Capabilities + */ + virtual Solid::Control::NetworkInterface::Capabilities capabilities() const = 0; + + protected: + //Q_SIGNALS: + /** + * This signal is emitted when the settings of this network have changed. + */ + virtual void ipDetailsChanged() = 0; + + /** + * This signal is emitted when the device's connection state changed. + * For example, if the device was disconnected and started to activate + * + * @param state the new state of the connection + * @see Solid::Control::NetworkInterface::ConnectionState + */ + virtual void connectionStateChanged(int state) = 0; + }; +} //Ifaces +} //Control +} //Solid + +Q_DECLARE_INTERFACE(Solid::Control::Ifaces::NetworkInterface, "org.kde.Solid.Control.Ifaces.NetworkInterface/0.1") + +#endif diff --git a/solid/control/ifaces/networkmanager.cpp b/solid/control/ifaces/networkmanager.cpp new file mode 100644 index 000000000..7e4ed0004 --- /dev/null +++ b/solid/control/ifaces/networkmanager.cpp @@ -0,0 +1,32 @@ +/* This file is part of the KDE project + Copyright (C) 2006 Will Stephenson + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#include "networkmanager.h" + +Solid::Control::Ifaces::NetworkManager::NetworkManager(QObject * parent) : QObject(parent) +{ + +} + +Solid::Control::Ifaces::NetworkManager::~NetworkManager() +{ + +} + +#include "networkmanager.moc" diff --git a/solid/control/ifaces/networkmanager.h b/solid/control/ifaces/networkmanager.h new file mode 100644 index 000000000..7cfa38fc1 --- /dev/null +++ b/solid/control/ifaces/networkmanager.h @@ -0,0 +1,170 @@ +/* This file is part of the KDE project + Copyright (C) 2006 Will Stephenson + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#ifndef SOLID_IFACES_NETWORKMANAGER +#define SOLID_IFACES_NETWORKMANAGER + +#include +#include +#include +#include "../solid_control_export.h" +#include "../networkmanager.h" + +namespace Solid +{ +namespace Control +{ +namespace Ifaces +{ + /** + * This class specifies the interface a backend will have to implement in + * order to be used in the system. + * + * A network manager allow to query the underlying platform to discover the + * available network interfaces and reachable network. It has also the + * responsibility to notify when a network interface or a network appear or disappear. + */ + class SOLIDCONTROLIFACES_EXPORT NetworkManager : public QObject + { + Q_OBJECT + public: + /** + * Constructs a NetworkManager. + * + * @param parent the parent object + */ + NetworkManager(QObject * parent = 0); + /** + * Destructs a NetworkManager object. + */ + virtual ~NetworkManager(); + + /** + * Get the manager connection state + */ + virtual Solid::Networking::Status status() const = 0; + + /** + * Retrieves the list of all the network interfaces Unique Network Identifiers (UNIs) + * in the system. It includes both hardware and virtual devices. + * + * @return the list of network interfaces available in this system + */ + virtual QStringList networkInterfaces() const = 0; + + /** + * Instantiates a new NetworkInterface object from this backend given its UNI. + * + * @param uni the identifier of the network interface instantiated + * @returns a new NetworkInterface object if there's a device having the given UNI, 0 otherwise + */ + virtual QObject *createNetworkInterface(const QString &uni) = 0; + + /** + * Retrieves the activation status of networking (as a whole) in the system. + * + * @return true if this networking is enabled, false otherwise + */ + virtual bool isNetworkingEnabled() const = 0; + + /** + * Retrieves the activation status of wireless networking in the system. + * + * @return true if this wireless networking is enabled, false otherwise + */ + virtual bool isWirelessEnabled() const = 0; + + /** + * Retrieves the status of wireless hardware in the system. This is typically + * controlled by a physical switch so there is no way to set this in software. + * + * @since KDE 4.1 + * @return true if this wireless networking is enabled, false otherwise + */ + virtual bool isWirelessHardwareEnabled() const = 0; + + virtual void activateConnection(const QString & interfaceUni, const QString & connectionUni, const QVariantMap & connectionParameters ) = 0; + + virtual void deactivateConnection(const QString & activeConnection) = 0; + + /** + * Access the list of active connection UNIs + */ + virtual QStringList activeConnections() const = 0; + + public Q_SLOTS: + /** + * Activates or deactivates networking (as a whole). + * + * @param enabled true to activate networking, false otherwise + */ + virtual void setNetworkingEnabled(bool enabled) = 0; + + /** + * Activates or deactivates wireless networking. + * + * @param enabled true to activate wireless networking, false otherwise + */ + virtual void setWirelessEnabled(bool enabled) = 0; + + Q_SIGNALS: + /** + * This signal is emitted when the system's connection state changes + */ + void statusChanged(Solid::Networking::Status status); + + /** + * This signal is emitted when a new network interface is available. + * + * @param uni the network interface identifier + */ + void networkInterfaceAdded(const QString & uni); + + /** + * This signal is emitted when a network interface is not available anymore. + * + * @param uni the network interface identifier + */ + void networkInterfaceRemoved(const QString & uni); + + /** + * This signal is emitted when the status of the wireless changed + */ + void wirelessEnabledChanged(bool enabled); + + /** + * This signal is emitted when the status of the wireless hardware changed + */ + void wirelessHardwareEnabledChanged(bool enabled); + + /** + * This signal is emitted when the set of active connections changes + */ + void activeConnectionsChanged(); + }; + +} // Ifaces + +} // Control + +} // Solid + +Q_DECLARE_INTERFACE(Solid::Control::Ifaces::NetworkManager, "org.kde.Solid.Control.Ifaces.NetworkManager/0.1") + +#endif diff --git a/solid/control/ifaces/networkserialinterface.cpp b/solid/control/ifaces/networkserialinterface.cpp new file mode 100644 index 000000000..b89ad3609 --- /dev/null +++ b/solid/control/ifaces/networkserialinterface.cpp @@ -0,0 +1,27 @@ +/* +Copyright 2008 Will Stephenson + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) version 3, or any +later version accepted by the membership of KDE e.V. (or its +successor approved by the membership of KDE e.V.), which shall +act as a proxy defined in Section 6 of version 3 of the license. + +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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library. If not, see . +*/ +#include "networkserialinterface.h" + +Solid::Control::Ifaces::SerialNetworkInterface::~SerialNetworkInterface() +{ + +} + +// vim: sw=4 sts=4 et tw=100 diff --git a/solid/control/ifaces/networkserialinterface.h b/solid/control/ifaces/networkserialinterface.h new file mode 100644 index 000000000..99fa84645 --- /dev/null +++ b/solid/control/ifaces/networkserialinterface.h @@ -0,0 +1,58 @@ +/* +Copyright 2008 Will Stephenson + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) version 3, or any +later version accepted by the membership of KDE e.V. (or its +successor approved by the membership of KDE e.V.), which shall +act as a proxy defined in Section 6 of version 3 of the license. 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library. If not, see . +*/ + +#ifndef SOLID_IFACES_SERIALNETWORKINTERFACE_H +#define SOLID_IFACES_SERIALNETWORKINTERFACE_H + +#include "../solid_control_export.h" + +#include + +#include "../networkserialinterface.h" +#include "networkinterface.h" + + +namespace Solid +{ +namespace Control +{ +namespace Ifaces +{ + /** + * Represents a wireless network interface + */ + class SOLIDCONTROLIFACES_EXPORT SerialNetworkInterface : virtual public NetworkInterface + { + public: + /** + * Destroys a SerialNetworkInterface object + */ + virtual ~SerialNetworkInterface(); + + protected: + //Q_SIGNALS: + void pppStats(uint in, uint out); + }; +} //Ifaces +} //Control +} //Solid + +Q_DECLARE_INTERFACE(Solid::Control::Ifaces::SerialNetworkInterface, "org.kde.Solid.Control.Ifaces.SerialNetworkInterface/0.1") + +#endif //SOLID_IFACES_SERIALNETWORKINTERFACE_H + diff --git a/solid/control/ifaces/powermanager.cpp b/solid/control/ifaces/powermanager.cpp new file mode 100644 index 000000000..e6bf7333d --- /dev/null +++ b/solid/control/ifaces/powermanager.cpp @@ -0,0 +1,34 @@ +/* This file is part of the KDE project + Copyright (C) 2006 Kevin Ottens + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#include "powermanager.h" + + +Solid::Control::Ifaces::PowerManager::PowerManager(QObject *parent) + : QObject(parent) +{ + +} + +Solid::Control::Ifaces::PowerManager::~PowerManager() +{ + +} + +#include "powermanager.moc" diff --git a/solid/control/ifaces/powermanager.h b/solid/control/ifaces/powermanager.h new file mode 100644 index 000000000..09cf1c57f --- /dev/null +++ b/solid/control/ifaces/powermanager.h @@ -0,0 +1,245 @@ +/* This file is part of the KDE project + Copyright (C) 2006 Kevin Ottens + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#ifndef SOLID_IFACES_POWERMANAGER_H +#define SOLID_IFACES_POWERMANAGER_H + +#include +#include + +#include "../solid_control_export.h" + +#include "../powermanager.h" + +class KJob; + +namespace Solid +{ +namespace Control +{ +namespace Ifaces +{ + /** + * This class specifies the interface a backend will have to implement in + * order to be used in the system. + * + * A power manager allows to control or query the power management features + * or the underlying platform. + */ + class SOLIDCONTROLIFACES_EXPORT PowerManager : public QObject + { + Q_OBJECT + + public: + /** + * Constructs a PowerManager + */ + PowerManager(QObject *parent = 0); + + /** + * Destructs a PowerManager object + */ + virtual ~PowerManager(); + + + /** + * Retrieves the list of power management schemes available on this system. + * + * @return the available power management schemes + */ + virtual QStringList supportedSchemes() const = 0; + + /** + * Retrieves a localized description corresponding to the given scheme. + * + * @param schemeName the name of the scheme we request the description for + * @return the associated description + */ + virtual QString schemeDescription(const QString &schemeName) const = 0; + + /** + * Retrieves the name of the current power management scheme used + * by the system. + * + * @return the current scheme + */ + virtual QString scheme() const = 0; + + /** + * Changes the current power management scheme. + * + * @param name the name of the new scheme + * @return true if the scheme change succeeded, false otherwise + */ + virtual bool setScheme(const QString &name) = 0; + + + /** + * Retrieves the current state of the system battery. + * + * @return the current battery state + * @see Solid::Control::PowerManager::BatteryState + */ + virtual Solid::Control::PowerManager::BatteryState batteryState() const = 0; + + /** + * Retrieves the current charge percentage of the system batteries. + * + * @return the current global battery charge percentage + */ + virtual int batteryChargePercent() const = 0; + + /** + * Retrieves the current state of the system AC adapter. + * + * @return the current AC adapter state + * @see Solid::Control::PowerManager::AcAdapterState + */ + virtual Solid::Control::PowerManager::AcAdapterState acAdapterState() const = 0; + + + /** + * Retrieves the set of suspend methods supported by the system. + * + * @return the suspend methods supported by this system + * @see Solid::Control::PowerManager::SuspendMethod + * @see Solid::Control::PowerManager::SuspendMethods + */ + virtual Solid::Control::PowerManager::SuspendMethods supportedSuspendMethods() const = 0; + + /** + * Requests a suspend of the system. + * + * @param method the suspend method to use + * @return the job handling the operation + */ + virtual KJob *suspend(Solid::Control::PowerManager::SuspendMethod method) const = 0; + + + /** + * Retrieves the set of CPU frequency policies supported by the system. + * + * @return the CPU frequency policies supported by this system + * @see Solid::Control::PowerManager::CpuFreqPolicy + * @see Solid::Control::PowerManager::CpuFreqPolicies + */ + virtual Solid::Control::PowerManager::CpuFreqPolicies supportedCpuFreqPolicies() const = 0; + + /** + * Retrieves the current CPU frequency policy of the system. + * + * @return the current CPU frequency policy used by the system + * @see Solid::Control::PowerManager::CpuFreqPolicy + */ + virtual Solid::Control::PowerManager::CpuFreqPolicy cpuFreqPolicy() const = 0; + + /** + * Changes the current CPU frequency policy of the system. + * + * @param newPolicy the new policy + * @return true if the policy change succeeded, false otherwise + * @see Solid::Control::PowerManager::CpuFreqPolicy + */ + virtual bool setCpuFreqPolicy(Solid::Control::PowerManager::CpuFreqPolicy newPolicy) = 0; + + /** + * Checks if a CPU can be disabled. + * + * @param cpuNum the number of the CPU we want to check + * @return true if the given CPU can be disabled, false otherwise + */ + virtual bool canDisableCpu(int cpuNum) const = 0; + + /** + * Enables or disables a CPU. + * + * @param cpuNum the number of the CPU we want to enable or disable + * @param enabled the new state of the CPU + * @return true if the state change succeeded, false otherwise + */ + virtual bool setCpuEnabled(int cpuNum, bool enabled) = 0; + + /** + * Checks if brightness controls are enabled on this system. + * + * @return a list of the devices available to control + */ + virtual Solid::Control::PowerManager::BrightnessControlsList brightnessControlsAvailable() = 0; + + /** + * Gets the screen brightness. + * + * @param device the name of the device that you would like to control + * @return the brightness of the device, as a percentage + */ + virtual float brightness(const QString &device = QString()) = 0; + + /** + * Sets the screen brightness. + * + * @param brightness the desired screen brightness, as a percentage + * @param device the name of the device that you would like to control, as given by brightnessControlsAvailable + * @return true if the brightness change succeeded, false otherwise + */ + virtual bool setBrightness(float brightness, const QString &panel = QString()) = 0; + + Q_SIGNALS: + /** + * This signal is emitted when the power management scheme has changed. + * + * @param newScheme the new scheme name + */ + void schemeChanged(QString newScheme); + + /** + * This signal is emitted when the AC adapter is plugged or unplugged. + * + * @param newState the new state of the AC adapter, it's one of the + * type @see Solid::Control::PowerManager::AcAdapterState + */ + void acAdapterStateChanged(int newState); + + /** + * This signal is emitted when the system battery state changed. + * + * @param newState the new state of the system battery, it's one of the + * type @see Solid::Control::PowerManager::BatteryState + */ + void batteryStateChanged(int newState); + + /** + * This signal is emitted when a button has been pressed. + * + * @param buttonType the pressed button type, it's one of the + * type @see Solid::Control::PowerManager::ButtonType + */ + void buttonPressed(int buttonType); + + /** + * This signal is emitted when the brightness changes. + * + * @param brightness the new brightness level + */ + void brightnessChanged(float brightness); + }; +} +} +} + +#endif diff --git a/solid/control/ifaces/wirednetworkinterface.cpp b/solid/control/ifaces/wirednetworkinterface.cpp new file mode 100644 index 000000000..e4f4907a9 --- /dev/null +++ b/solid/control/ifaces/wirednetworkinterface.cpp @@ -0,0 +1,26 @@ +/* This file is part of the KDE project + Copyright (C) 2006 Will Stephenson + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#include "wirednetworkinterface.h" + +Solid::Control::Ifaces::WiredNetworkInterface::~WiredNetworkInterface() +{ + +} + diff --git a/solid/control/ifaces/wirednetworkinterface.h b/solid/control/ifaces/wirednetworkinterface.h new file mode 100644 index 000000000..6d4a95f93 --- /dev/null +++ b/solid/control/ifaces/wirednetworkinterface.h @@ -0,0 +1,85 @@ +/* This file is part of the KDE project + Copyright (C) 2006,2007 Will Stephenson + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#ifndef SOLID_IFACES_WIREDNETWORKINTERFACE_H +#define SOLID_IFACES_WIREDNETWORKINTERFACE_H + +#include "../solid_control_export.h" + +#include + +#include "networkinterface.h" + + +namespace Solid +{ +namespace Control +{ +namespace Ifaces +{ + /** + * Represents a wired network interface + */ + class SOLIDCONTROLIFACES_EXPORT WiredNetworkInterface : virtual public NetworkInterface + { + public: + /** + * Destroys a WiredNetworkInterface object + */ + virtual ~WiredNetworkInterface(); + /** + * The hardware address assigned to the network interface + */ + virtual QString hardwareAddress() const = 0; + /** + * Retrieves the effective bit rate currently attainable by this device. + * + * @return the bitrate in bit/s + */ + virtual int bitRate() const = 0; + + /** + * Indicates if the network interfaces sees a carrier. + * + * @return true if there's a carrier, false otherwise + */ + virtual bool carrier() const = 0; + + protected: + //Q_SIGNALS: + /** + * This signal is emitted when the bitrate of this network has changed. + * + * @param bitrate the new bitrate value for this network + */ + virtual void bitRateChanged(int bitRate) = 0; + /** + * This signal indicates if the physical carrier changed state (eg if the network cable was + * plugged or unplugged) + */ + virtual void carrierChanged(bool plugged) = 0; + }; +} //Ifaces +} //Control +} //Solid + +Q_DECLARE_INTERFACE(Solid::Control::Ifaces::WiredNetworkInterface, "org.kde.Solid.Control.Ifaces.WiredNetworkInterface/0.1") + +#endif // SOLID_IFACES_WIRELESSNETWORKINTERFACE_H + diff --git a/solid/control/ifaces/wirelessaccesspoint.cpp b/solid/control/ifaces/wirelessaccesspoint.cpp new file mode 100644 index 000000000..f02c3eb27 --- /dev/null +++ b/solid/control/ifaces/wirelessaccesspoint.cpp @@ -0,0 +1,31 @@ +/* +Copyright 2008 Will Stephenson + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) version 3, or any +later version accepted by the membership of KDE e.V. (or its +successor approved by the membership of KDE e.V.), which shall +act as a proxy defined in Section 6 of version 3 of the license. + +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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library. If not, see . +*/ + +#include "wirelessaccesspoint.h" + +Solid::Control::Ifaces::AccessPoint::AccessPoint(QObject * parent) : QObject(parent) +{ + +} +Solid::Control::Ifaces::AccessPoint::~AccessPoint() +{ + +} + diff --git a/solid/control/ifaces/wirelessaccesspoint.h b/solid/control/ifaces/wirelessaccesspoint.h new file mode 100644 index 000000000..315faefff --- /dev/null +++ b/solid/control/ifaces/wirelessaccesspoint.h @@ -0,0 +1,157 @@ +/* +Copyright 2008 Will Stephenson + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) version 3, or any +later version accepted by the membership of KDE e.V. (or its +successor approved by the membership of KDE e.V.), which shall +act as a proxy defined in Section 6 of version 3 of the license. + +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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library. If not, see . +*/ + +#ifndef SOLIDCONTROL_IFACES_WIRELESSAP_H +#define SOLIDCONTROL_IFACES_WIRELESSAP_H + +#include "../solid_control_export.h" +#include "../wirelessaccesspoint.h" +#include "../wirelessnetworkinterface.h" + +namespace Solid +{ +namespace Control +{ +namespace Ifaces +{ + /** + * A wireless Access Point or another station acting in ad-hoc mode + */ + class SOLIDCONTROLIFACES_EXPORT AccessPoint : public QObject + { + Q_OBJECT + public: + AccessPoint(QObject *); + /** + * Destructor + */ + virtual ~AccessPoint(); + + /** + * Unique identifer for this access point + */ + virtual QString uni() const = 0; + + /** + * Flags describing the capabilities of the access point + */ + virtual Solid::Control::AccessPoint::Capabilities capabilities() const = 0; + + /** + * Flags describing the access point's capabilities according to WPA (Wifi Protected Access) + */ + virtual Solid::Control::AccessPoint::WpaFlags wpaFlags() const = 0; + + /** + * Flags describing the access point's capabilities according to RSN (Robust Secure Network) + * aka WPA2 + */ + virtual Solid::Control::AccessPoint::WpaFlags rsnFlags() const = 0; + + /** + * The Service Set Identifier of the access point + */ + virtual QString ssid() const = 0; + + /** + * Retrieves the frequency in MHz of the radio channel that this access point is operating on + * + * @return the frequency + */ + virtual uint frequency() const = 0; + + /** + * The hardware address assigned to the access point's wireless interface, in hex-and-colon + * form + */ + virtual QString hardwareAddress() const = 0; + + /** + * Retrieves the maximum bit rate currently attainable by this device. + * + * @return the maximum bitrate in kilobit/s + */ + virtual uint maxBitRate() const = 0; + + /** + * Retrieves the operation mode of this access point + * + * @return the current mode + * @see Solid::Control::WirelessNetworkInterface::OperationMode + */ + virtual Solid::Control::WirelessNetworkInterface::OperationMode mode() const = 0; + + /** + * Retrieves the current signal strength of this wifi network. + * + * @return the signal strength as a percentage + */ + virtual int signalStrength() const = 0; + + Q_SIGNALS: + /** + * This signal is emitted when the signal strength of this network has changed. + * + * @param strength the new signal strength value for this network + */ + void signalStrengthChanged(int strength); + + /** + * This signal is emitted when the bitrate of this network has changed. + * + * @param bitrate the new bitrate value for this network + */ + void bitRateChanged(int bitrate); + + /** + * This signal is emitted when the WPA flags in use by this access point change + * + * @param flags the new flags + */ + void wpaFlagsChanged(Solid::Control::AccessPoint::WpaFlags flags); + + /** + * This signal is emitted when the RSN(WPA2) flags in use by this access point change + * + * @param flags the new flags + */ + void rsnFlagsChanged(Solid::Control::AccessPoint::WpaFlags flags); + /** + * This signal is emitted when the ssid of this Access Point changes + * + * @param ssid the new SSID + */ + void ssidChanged(const QString &ssid); + + /** + * This signal is emitted when the frequency used by this Access Point changes + * + * @param frequency the new frequency + */ + void frequencyChanged(uint frequency); + }; +} +} +} + +Q_DECLARE_INTERFACE(Solid::Control::Ifaces::AccessPoint, "org.kde.Solid.Control.Ifaces.AccessPoint/0.1") + +#endif // SOLIDCONTROL_IFACES_WIRELESSAP_H + diff --git a/solid/control/ifaces/wirelessnetworkinterface.cpp b/solid/control/ifaces/wirelessnetworkinterface.cpp new file mode 100644 index 000000000..b4583ddad --- /dev/null +++ b/solid/control/ifaces/wirelessnetworkinterface.cpp @@ -0,0 +1,28 @@ +/* This file is part of the KDE project + Copyright (C) 2006 Will Stephenson + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#include "wirelessnetworkinterface.h" + +Solid::Control::Ifaces::WirelessNetworkInterface::~WirelessNetworkInterface() +{ + +} + + + diff --git a/solid/control/ifaces/wirelessnetworkinterface.h b/solid/control/ifaces/wirelessnetworkinterface.h new file mode 100644 index 000000000..1e6d90934 --- /dev/null +++ b/solid/control/ifaces/wirelessnetworkinterface.h @@ -0,0 +1,123 @@ +/* This file is part of the KDE project + Copyright (C) 2006,2007,2008 Will Stephenson + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#ifndef SOLID_IFACES_WIRELESSNETWORKINTERFACE_H +#define SOLID_IFACES_WIRELESSNETWORKINTERFACE_H + +#include "../solid_control_export.h" + +#include + +#include "../wirelessnetworkinterface.h" +#include "networkinterface.h" + + +typedef QString MacAddress; +typedef QStringList MacAddressList; + +namespace Solid +{ +namespace Control +{ +namespace Ifaces +{ + /** + * Represents a wireless network interface + */ + class SOLIDCONTROLIFACES_EXPORT WirelessNetworkInterface : virtual public NetworkInterface + { + public: + /** + * Destroys a WirelessNetworkInterface object + */ + virtual ~WirelessNetworkInterface(); + /** + * List of wireless networks currently visible to the hardware + */ + virtual MacAddressList accessPoints() const = 0; + /** + * Identifier of the network this interface is currently associated with + */ + virtual QString activeAccessPoint() const = 0; + /** + * The hardware address assigned to the network interface + */ + virtual QString hardwareAddress() const = 0; + /** + * Retrieves the operation mode of this network. + * + * @return the current mode + * @see Solid::Control::WirelessNetworkInterface::OperationMode + */ + virtual Solid::Control::WirelessNetworkInterface::OperationMode mode() const = 0; + + /** + * Retrieves the effective bit rate currently attainable by this device. + * + * @return the bitrate in bit/s + */ + virtual int bitRate() const = 0; + + /** + * Retrieves the capabilities of this wifi network. + * + * @return the flag set describing the capabilities + * @see Solid::Control::WirelessNetworkInterface::DeviceInterface + */ + virtual Solid::Control::WirelessNetworkInterface::Capabilities wirelessCapabilities() const = 0; + /** + * Instantiates a new AccessPoint object from the current backend given its UNI. + * + * @param uni the identifier of the network instantiated + * @returns a new AccessPoint object if there's a network having the given UNI for this device, 0 otherwise + */ + virtual QObject * createAccessPoint(const QString & uni) = 0; + protected: + //Q_SIGNALS: + /** + * This signal is emitted when the bitrate of this network has changed. + * + * @param bitrate the new bitrate value for this network + */ + virtual void bitRateChanged(int bitrate) = 0; + /** + * The accesspoint in use changed. + */ + virtual void activeAccessPointChanged(const QString &) = 0; + /** + * The device switched operating mode. + */ + virtual void modeChanged(Solid::Control::WirelessNetworkInterface::OperationMode) = 0; + /** + * A new wireless access point appeared + */ + virtual void accessPointAppeared(const QString &) = 0; + /** + * A wireless access point disappeared + */ + virtual void accessPointDisappeared(const QString &) = 0; + }; +} //Ifaces +} //Control +} //Solid + +Q_DECLARE_INTERFACE(Solid::Control::Ifaces::WirelessNetworkInterface, "org.kde.Solid.Control.Ifaces.WirelessNetworkInterface/0.1") + +#endif //SOLID_IFACES_WIRELESSNETWORKINTERFACE_H + diff --git a/solid/control/managerbase.cpp b/solid/control/managerbase.cpp new file mode 100644 index 000000000..4a6af2695 --- /dev/null +++ b/solid/control/managerbase.cpp @@ -0,0 +1,115 @@ +/* This file is part of the KDE project + Copyright (C) 2006-2007 Kevin Ottens + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#include "managerbase_p.h" + +#include +#include +#include + +#include +#include + +static QMap _k_preloadedBackends; + +Solid::Control::ManagerBasePrivate::ManagerBasePrivate() + : m_backend(0) +{ +} + +Solid::Control::ManagerBasePrivate::~ManagerBasePrivate() +{ +} + +void Solid::Control::ManagerBasePrivate::loadBackend(const QString &description, const char *serviceName, + const char *backendClassName) +{ + if (_k_preloadedBackends.contains(backendClassName)) { + m_backend = _k_preloadedBackends[backendClassName]; + return; + } + + QStringList error_msg; + + KService::List offers = KServiceTypeTrader::self()->query(serviceName, "(Type == 'Service')"); + + foreach (const KService::Ptr &ptr, offers) + { + QString error_string; + m_backend = ptr->createInstance(0, QVariantList(), &error_string); + + if(m_backend!=0) { + if (m_backend->inherits(backendClassName)) { + kDebug() << "Backend loaded: " << ptr->name(); + break; + } else { + QString error_string = i18n("Backend loaded but wrong type obtained, expected %1", + backendClassName); + + kDebug() << "Error loading '" << ptr->name() << "': " << error_string; + error_msg.append(error_string); + + delete m_backend; + m_backend = 0; + } + } else { + kDebug() << "Error loading '" << ptr->name() << "', KService said: " << error_string; + error_msg.append(error_string); + } + } + + if (m_backend==0) { + if (offers.size() == 0) + { + m_errorText = i18n("No %1 Backend found", description); + } + else + { + m_errorText = ""; + m_errorText+= i18n("Unable to use any of the %1 Backends", description); + m_errorText+= ""; + + QString line = ""; + + for (int i = 0; i< offers.size(); i++) + { + m_errorText+= line.arg(offers[i]->name()).arg(error_msg[i]); + } + + m_errorText+= "
    %1%2
    "; + } + } +} + +QString Solid::Control::ManagerBasePrivate::errorText() const +{ + return m_errorText; +} + +QObject *Solid::Control::ManagerBasePrivate::managerBackend() const +{ + return m_backend; +} + +void Solid::Control::ManagerBasePrivate::_k_forcePreloadedBackend(const char *backendClassName, QObject *backend) +{ + _k_preloadedBackends[backendClassName] = backend; +} + + diff --git a/solid/control/managerbase_p.h b/solid/control/managerbase_p.h new file mode 100644 index 000000000..fd1a81303 --- /dev/null +++ b/solid/control/managerbase_p.h @@ -0,0 +1,51 @@ +/* This file is part of the KDE project + Copyright (C) 2006-2007 Kevin Ottens + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#ifndef SOLID_MANAGERBASE_P_H +#define SOLID_MANAGERBASE_P_H + +#include +#include + +#include "solid/control/solid_control_export.h" + +namespace Solid +{ +namespace Control +{ + class ManagerBasePrivate + { + public: + ManagerBasePrivate(); + virtual ~ManagerBasePrivate(); + void loadBackend(const QString &description, const char *serviceName, const char *backendClassName); + + SOLIDCONTROL_EXPORT static void _k_forcePreloadedBackend(const char *backendClassName, QObject *backend); + + QObject *managerBackend() const; + QString errorText() const; + + private: + QObject *m_backend; + QString m_errorText; + }; +} +} + +#endif diff --git a/solid/control/network_p.h b/solid/control/network_p.h new file mode 100644 index 000000000..fb88d4a53 --- /dev/null +++ b/solid/control/network_p.h @@ -0,0 +1,41 @@ +/* This file is part of the KDE project + Copyright (C) 2006 Will Stephenson + Copyright (C) 2007 Kevin Ottens + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#ifndef SOLID_NETWORK_P_H +#define SOLID_NETWORK_P_H + +#include "frontendobject_p.h" + +namespace Solid +{ +namespace Control +{ + class NetworkPrivate : public FrontendObjectPrivate + { + public: + explicit NetworkPrivate(QObject *parent) + : FrontendObjectPrivate(parent) { } + + void setBackendObject(QObject *object); + }; +} +} + +#endif diff --git a/solid/control/networkcdmainterface.cpp b/solid/control/networkcdmainterface.cpp new file mode 100644 index 000000000..8883378e7 --- /dev/null +++ b/solid/control/networkcdmainterface.cpp @@ -0,0 +1,77 @@ +/* Copyright 2008 Will Stephenson + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) version 3, or any +later version accepted by the membership of KDE e.V. (or its +successor approved by the membership of KDE e.V.), which shall +act as a proxy defined in Section 6 of version 3 of the license. + +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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library. If not, see . +*/ + +#include "networkcdmainterface.h" +#include "networkcdmainterface_p.h" + +#include "frontendobject_p.h" +#include "soliddefs_p.h" +#include "ifaces/wirelessaccesspoint.h" + +Solid::Control::CdmaNetworkInterface::CdmaNetworkInterface(QObject *backendObject) + : SerialNetworkInterface(*new CdmaNetworkInterfacePrivate(this), backendObject) +{ + Q_D(CdmaNetworkInterface); + d->setBackendObject(backendObject); + makeConnections( backendObject ); +} + +Solid::Control::CdmaNetworkInterface::CdmaNetworkInterface(const CdmaNetworkInterface &networkinterface) + : SerialNetworkInterface(*new CdmaNetworkInterfacePrivate(this), networkinterface) +{ + Q_D(CdmaNetworkInterface); + d->setBackendObject(networkinterface.d_ptr->backendObject()); + makeConnections( networkinterface.d_ptr->backendObject() ); +} + +Solid::Control::CdmaNetworkInterface::CdmaNetworkInterface(CdmaNetworkInterfacePrivate &dd, QObject *backendObject) + : SerialNetworkInterface(dd, backendObject) +{ + makeConnections( backendObject ); +} + +Solid::Control::CdmaNetworkInterface::CdmaNetworkInterface(CdmaNetworkInterfacePrivate &dd, const CdmaNetworkInterface &networkinterface) + : SerialNetworkInterface(dd, networkinterface.d_ptr->backendObject()) +{ + makeConnections( networkinterface.d_ptr->backendObject() ); +} + +Solid::Control::CdmaNetworkInterface::~CdmaNetworkInterface() +{ +} + +Solid::Control::NetworkInterface::Type Solid::Control::CdmaNetworkInterface::type() const +{ + return Cdma; +} + +void Solid::Control::CdmaNetworkInterface::makeConnections(QObject * source) +{ +} + +void Solid::Control::CdmaNetworkInterfacePrivate::setBackendObject(QObject *object) +{ + SerialNetworkInterfacePrivate::setBackendObject(object); +} + +void Solid::Control::CdmaNetworkInterface::_k_destroyed(QObject *object) +{ + Q_UNUSED(object); +} +// vim: sw=4 sts=4 et tw=100 diff --git a/solid/control/networkcdmainterface.h b/solid/control/networkcdmainterface.h new file mode 100644 index 000000000..2648210bc --- /dev/null +++ b/solid/control/networkcdmainterface.h @@ -0,0 +1,89 @@ +/* +Copyright 2008 Will Stephenson + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) version 3, or any +later version accepted by the membership of KDE e.V. (or its +successor approved by the membership of KDE e.V.), which shall +act as a proxy defined in Section 6 of version 3 of the license. + +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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library. If not, see . +*/ + +#ifndef SOLID_CONTROL_CDMANETWORKINTERFACE_H +#define SOLID_CONTROL_CDMANETWORKINTERFACE_H + +#include "networkserialinterface.h" + +namespace Solid +{ +namespace Control +{ + class CdmaNetworkInterfacePrivate; + /** + * This interface represents a CDMA cellular network interface + */ + class SOLIDCONTROL_EXPORT CdmaNetworkInterface : public SerialNetworkInterface + { + Q_OBJECT + Q_DECLARE_PRIVATE(CdmaNetworkInterface) + + public: + /** + * Creates a new CdmaNetworkInterface object. + * + * @param backendObject the network object provided by the backend + */ + CdmaNetworkInterface(QObject *backendObject = 0); + + /** + * Constructs a copy of a network. + * + * @param network the network to copy + */ + CdmaNetworkInterface(const CdmaNetworkInterface &network); + + /** + * Destroys a CdmaNetworkInterface object. + */ + virtual ~CdmaNetworkInterface(); + + /** + * The NetworkInterface type. + * + * @return the NetworkInterface::Type. This always returns NetworkInterface::Cdma + */ + virtual NetworkInterface::Type type() const; + + Q_SIGNALS: + protected: + /** + * @internal + */ + CdmaNetworkInterface(CdmaNetworkInterfacePrivate &dd, QObject *backendObject); + + /** + * @internal + */ + CdmaNetworkInterface(CdmaNetworkInterfacePrivate &dd, const CdmaNetworkInterface &network); + + void makeConnections(QObject * source); + private Q_SLOTS: + void _k_destroyed(QObject *object); + private: + friend class NetworkInterface; + friend class NetworkInterfacePrivate; + }; +} //Control +} //Solid + +#endif // SOLID_CONTROL_CDMANETWORKINTERFACE_H + diff --git a/solid/control/networkcdmainterface_p.h b/solid/control/networkcdmainterface_p.h new file mode 100644 index 000000000..da42a738a --- /dev/null +++ b/solid/control/networkcdmainterface_p.h @@ -0,0 +1,41 @@ +/* +Copyright 2008 Will Stephenson + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) version 3, or any +later version accepted by the membership of KDE e.V. (or its +successor approved by the membership of KDE e.V.), which shall +act as a proxy defined in Section 6 of version 3 of the license. + +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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library. If not, see . +*/ + +#ifndef SOLID_CONTROL_CDMANETWORKINTERFACE_P_H +#define SOLID_CONTROL_CDMANETWORKINTERFACE_P_H + +#include "networkserialinterface_p.h" + +namespace Solid +{ +namespace Control +{ + class CdmaNetworkInterfacePrivate : public SerialNetworkInterfacePrivate + { + public: + explicit CdmaNetworkInterfacePrivate(QObject *parent) + : SerialNetworkInterfacePrivate(parent) { } + + void setBackendObject(QObject *object); + }; +} +} + +#endif //SOLID_CONTROL_CDMANETWORKINTERFACE_P_H diff --git a/solid/control/networkgsminterface.cpp b/solid/control/networkgsminterface.cpp new file mode 100644 index 000000000..1c69b4703 --- /dev/null +++ b/solid/control/networkgsminterface.cpp @@ -0,0 +1,78 @@ +/* +Copyright 2008 Will Stephenson + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) version 3, or any +later version accepted by the membership of KDE e.V. (or its +successor approved by the membership of KDE e.V.), which shall +act as a proxy defined in Section 6 of version 3 of the license. + +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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library. If not, see . +*/ + +#include "networkgsminterface.h" +#include "networkgsminterface_p.h" + +#include "frontendobject_p.h" +#include "soliddefs_p.h" +#include "ifaces/wirelessaccesspoint.h" + +Solid::Control::GsmNetworkInterface::GsmNetworkInterface(QObject *backendObject) + : SerialNetworkInterface(*new GsmNetworkInterfacePrivate(this), backendObject) +{ + Q_D(GsmNetworkInterface); + d->setBackendObject(backendObject); + makeConnections( backendObject ); +} + +Solid::Control::GsmNetworkInterface::GsmNetworkInterface(const GsmNetworkInterface &networkinterface) + : SerialNetworkInterface(*new GsmNetworkInterfacePrivate(this), networkinterface) +{ + Q_D(GsmNetworkInterface); + d->setBackendObject(networkinterface.d_ptr->backendObject()); + makeConnections( networkinterface.d_ptr->backendObject() ); +} + +Solid::Control::GsmNetworkInterface::GsmNetworkInterface(GsmNetworkInterfacePrivate &dd, QObject *backendObject) + : SerialNetworkInterface(dd, backendObject) +{ + makeConnections( backendObject ); +} + +Solid::Control::GsmNetworkInterface::GsmNetworkInterface(GsmNetworkInterfacePrivate &dd, const GsmNetworkInterface &networkinterface) + : SerialNetworkInterface(dd, networkinterface.d_ptr->backendObject()) +{ + makeConnections( networkinterface.d_ptr->backendObject() ); +} + +Solid::Control::GsmNetworkInterface::~GsmNetworkInterface() +{ +} + +Solid::Control::NetworkInterface::Type Solid::Control::GsmNetworkInterface::type() const +{ + return Gsm; +} + +void Solid::Control::GsmNetworkInterface::makeConnections(QObject * source) +{ +} + +void Solid::Control::GsmNetworkInterfacePrivate::setBackendObject(QObject *object) +{ + SerialNetworkInterfacePrivate::setBackendObject(object); +} + +void Solid::Control::GsmNetworkInterface::_k_destroyed(QObject *object) +{ + Q_UNUSED(object); +} +// vim: sw=4 sts=4 et tw=100 diff --git a/solid/control/networkgsminterface.h b/solid/control/networkgsminterface.h new file mode 100644 index 000000000..38a981f32 --- /dev/null +++ b/solid/control/networkgsminterface.h @@ -0,0 +1,89 @@ +/* +Copyright 2008 Will Stephenson + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) version 3, or any +later version accepted by the membership of KDE e.V. (or its +successor approved by the membership of KDE e.V.), which shall +act as a proxy defined in Section 6 of version 3 of the license. + +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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library. If not, see . +*/ + +#ifndef SOLID_CONTROL_GSMNETWORKINTERFACE_H +#define SOLID_CONTROL_GSMNETWORKINTERFACE_H + +#include "networkserialinterface.h" + +namespace Solid +{ +namespace Control +{ + class GsmNetworkInterfacePrivate; + /** + * This interface represents a GSM cellular network interface + */ + class SOLIDCONTROL_EXPORT GsmNetworkInterface : public SerialNetworkInterface + { + Q_OBJECT + Q_DECLARE_PRIVATE(GsmNetworkInterface) + + public: + /** + * Creates a new GsmNetworkInterface object. + * + * @param backendObject the network object provided by the backend + */ + GsmNetworkInterface(QObject *backendObject = 0); + + /** + * Constructs a copy of a network. + * + * @param network the network to copy + */ + GsmNetworkInterface(const GsmNetworkInterface &network); + + /** + * Destroys a GsmNetworkInterface object. + */ + virtual ~GsmNetworkInterface(); + + /** + * The NetworkInterface type. + * + * @return the NetworkInterface::Type. This always returns NetworkInterface::Ieee8023 + */ + virtual NetworkInterface::Type type() const; + + Q_SIGNALS: + protected: + /** + * @internal + */ + GsmNetworkInterface(GsmNetworkInterfacePrivate &dd, QObject *backendObject); + + /** + * @internal + */ + GsmNetworkInterface(GsmNetworkInterfacePrivate &dd, const GsmNetworkInterface &network); + + void makeConnections(QObject * source); + private Q_SLOTS: + void _k_destroyed(QObject *object); + private: + friend class NetworkInterface; + friend class NetworkInterfacePrivate; + }; +} //Control +} //Solid + +#endif // SOLID_CONTROL_GSMNETWORKINTERFACE_H + diff --git a/solid/control/networkgsminterface_p.h b/solid/control/networkgsminterface_p.h new file mode 100644 index 000000000..845a7f830 --- /dev/null +++ b/solid/control/networkgsminterface_p.h @@ -0,0 +1,41 @@ +/* +Copyright 2008 Will Stephenson + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) version 3, or any +later version accepted by the membership of KDE e.V. (or its +successor approved by the membership of KDE e.V.), which shall +act as a proxy defined in Section 6 of version 3 of the license. + +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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library. If not, see . +*/ + +#ifndef SOLID_CONTROL_GSMNETWORKINTERFACE_P_H +#define SOLID_CONTROL_GSMNETWORKINTERFACE_P_H + +#include "networkserialinterface_p.h" + +namespace Solid +{ +namespace Control +{ + class GsmNetworkInterfacePrivate : public SerialNetworkInterfacePrivate + { + public: + explicit GsmNetworkInterfacePrivate(QObject *parent) + : SerialNetworkInterfacePrivate(parent) { } + + void setBackendObject(QObject *object); + }; +} +} + +#endif //SOLID_CONTROL_GSMNETWORKINTERFACE_P_H diff --git a/solid/control/networking.cpp b/solid/control/networking.cpp new file mode 100644 index 000000000..a630ef8c2 --- /dev/null +++ b/solid/control/networking.cpp @@ -0,0 +1,323 @@ +/* This file is part of the KDE project + Copyright (C) 2006-2007 Will Stephenson + Copyright (C) 2006-2007 Kevin Ottens + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#include +#include + +#include + +#include "networking_p.h" +#include "networking.h" +#include "org_kde_solid_networking.h" + +K_GLOBAL_STATIC(Solid::Control::NetworkingPrivate, globalNetworkControl) + +Solid::Control::NetworkingPrivate::NetworkingPrivate() : iface( + new OrgKdeSolidNetworkingInterface( "org.kde.Solid.Networking", + "/status", + QDBusConnection::sessionBus(), + this ) ) +{ +} + +Solid::Control::NetworkingPrivate::~NetworkingPrivate() +{ +}uint Solid::Control::NetworkingPrivate::requestConnection( QObject * receiver, const char * member ) +{ + connect( this, SIGNAL( connectionResult( bool ) ), receiver, member ); + return iface->requestConnection(); +} + +void Solid::Control::NetworkingPrivate::releaseConnection() +{ + iface->releaseConnection(); +} + +Solid::Control::Networking::Result Solid::Control::NetworkingPrivate::beginManagingSocket( QAbstractSocket * socket, int autoDisconnectTimeout ) +{ + mManagedSockets.insert( socket, new ManagedSocketContainer( socket, autoDisconnectTimeout ) ); + return Solid::Control::Networking::Accepted; +} + +void Solid::Control::NetworkingPrivate::stopManagingSocket( QAbstractSocket * socket ) +{ + ManagedSocketContainer * removed = mManagedSockets.take( socket ); + delete removed; +} + +Solid::Control::Networking::Result Solid::Control::Networking::requestConnection( QObject * receiver, const char * member ) +{ + return static_cast( globalNetworkControl->requestConnection( receiver, member ) ); +} + +void Solid::Control::Networking::releaseConnection() +{ + globalNetworkControl->releaseConnection(); +} + +/*=========================================================================*/ + + +Solid::Control::ManagedSocketContainer::ManagedSocketContainer( QAbstractSocket * socket, int autoDisconnectTimeout ) : mSocket( socket ), mAutoDisconnectTimer( 0 ) +{ + if ( autoDisconnectTimeout >= 0 ) + { + mAutoDisconnectTimer = new QTimer( this ); + mAutoDisconnectTimer->setSingleShot( true ); + mAutoDisconnectTimer->setInterval( autoDisconnectTimeout ); + connect( mAutoDisconnectTimer, SIGNAL( timeout() ), SLOT( autoDisconnect() ) ); + } + // react to network management events + connect( Solid::Networking::notifier(), SIGNAL( statusChanged( uint ) ), this, SLOT( networkStatusChanged( Networking::Status ) ) ); + + if ( socket ) + { + // react to socket events + connect( socket, SIGNAL( destroyed() ), SLOT( socketDestroyed() ) ); + connect( socket, SIGNAL( error( QAbstractSocket::SocketError ) ), SLOT( socketError( QAbstractSocket::SocketError ) ) ); + connect( socket, SIGNAL( stateChanged( QAbstractSocket::SocketState ) ), SLOT( socketStateChanged( QAbstractSocket::SocketState ) ) ); + // initialise our state from that of the socket + switch ( socket->state() ) + { + case QAbstractSocket::UnconnectedState: + mState = SocketUnconnected; + break; + case QAbstractSocket::HostLookupState: + case QAbstractSocket::ConnectingState: + mState = SocketConnecting; + break; + case QAbstractSocket::ConnectedState: + case QAbstractSocket::ClosingState: + mState = SocketConnected; + break; + default: + mState = SocketUnconnected; + } + } +} + +void Solid::Control::ManagedSocketContainer::networkStatusChanged( Solid::Networking::Status netStatus ) +{ + switch ( mState ) + { + case SocketUnconnected: + break; + case SocketConnecting: + break; + case AwaitingNetworkConnection: + switch ( netStatus ) + { + case Solid::Networking::Connected: + performConnectToHost(); + break; + default: + //do nothing + ; + } + break; + case SocketConnected: + switch ( netStatus ) + { + case Solid::Networking::Unconnected: + case Solid::Networking::Disconnecting: + mState = DisconnectWait; + if ( mAutoDisconnectTimer ) + { + mAutoDisconnectTimer->start(); + } + break; + default: + // do nothing + ; + } + break; + case DisconnectWait: + switch ( netStatus ) + { + case Solid::Networking::Connected: + // RECOVERED + mState = SocketConnected; + if ( mAutoDisconnectTimer ) + { + mAutoDisconnectTimer->stop(); + } + break; + default: + // do nothing + ; + } + break; + } +} + +void Solid::Control::ManagedSocketContainer::socketError( QAbstractSocket::SocketError socketError ) +{ + switch ( mState ) + { + case SocketUnconnected: + break; + case SocketConnecting: + switch ( socketError ) + { + case QAbstractSocket::HostNotFoundError: + case QAbstractSocket::NetworkError: + // socket tried to resolve and failed + // Either the host doesn't exist at all + // or the resolve failed because we're offline, so request that we go online + if ( Solid::Networking::status() != Solid::Networking::Connected ) + { + mState = AwaitingNetworkConnection; + globalNetworkControl->requestConnection(); + } + else + { + mState = SocketUnconnected; + } + break; + default: + mState = SocketUnconnected; + } + break; + case AwaitingNetworkConnection: + case SocketConnected: + // setup automatic reconnect now when/if we impl this + case DisconnectWait: + // maybe check the socket state that it thinks it is now unconnected too + mState = SocketUnconnected; + break; + } +} + +void Solid::Control::ManagedSocketContainer::socketStateChanged( QAbstractSocket::SocketState socketState ) +{ + switch ( mState ) + { + case SocketUnconnected: + switch ( socketState ) + { + case QAbstractSocket::HostLookupState: + case QAbstractSocket::ConnectingState: + // the socket is trying to connect, cache its connection parameter in case it + // fails and we want to reconnect it when the network is available. + mState = SocketConnecting; + if ( mSocket ) + { + mPeerName = mSocket->peerName(); + mPeerPort = mSocket->peerPort(); + mSocketOpenMode = mSocket->openMode(); + } + break; + default: + ; + } + break; + case SocketConnecting: + switch ( socketState ) + { + case QAbstractSocket::HostLookupState: + case QAbstractSocket::ConnectingState: + // still connecting, do nothing + break; + case QAbstractSocket::BoundState: + case QAbstractSocket::ConnectedState: + case QAbstractSocket::ListeningState: + // socket connected unaided + mState = SocketConnected; + break; + case QAbstractSocket::UnconnectedState: + // this state is preceded by ClosingState, so no action needed + break; + case QAbstractSocket::ClosingState: + // it's unlikely that an unconnected socket can go to this state, but... + mState = SocketUnconnected; + break; + } + break; + case AwaitingNetworkConnection: + switch ( socketState ) + { + case QAbstractSocket::ConnectedState: + // somehow the socket connected itself when it shouldn't have been able to. + mState = SocketConnected; + + break; + default: + //do nothing + ; + } + break; + case SocketConnected: + switch ( socketState ) + { + case QAbstractSocket::UnconnectedState: + case QAbstractSocket::ClosingState: + // socket disconnected + mState = SocketUnconnected; + break; + case QAbstractSocket::ConnectingState: + mState = SocketConnected; + break; + default: + ; + } + break; + case DisconnectWait: + switch ( socketState ) + { + case QAbstractSocket::UnconnectedState: + case QAbstractSocket::ClosingState: + // socket disconnected anyway + mState = SocketUnconnected; + if ( mAutoDisconnectTimer ) + { + mAutoDisconnectTimer->stop(); + } + break; + default: + break; + } + break; + } +} + +void Solid::Control::ManagedSocketContainer::autoDisconnect() +{ + if ( mAutoDisconnectTimer && mSocket ) + mSocket->disconnectFromHost(); +} + +void Solid::Control::ManagedSocketContainer::socketDestroyed() +{ + mSocket = 0; + delete mAutoDisconnectTimer; + mAutoDisconnectTimer = 0; + disconnect( globalNetworkControl ); +} + +void Solid::Control::ManagedSocketContainer::performConnectToHost() +{ + if ( mSocket ) + { + mSocket->connectToHost( mPeerName, mPeerPort, mSocketOpenMode ); + } +} + +#include "networking_p.moc" +#include "networking.moc" diff --git a/solid/control/networking.h b/solid/control/networking.h new file mode 100644 index 000000000..1b7a8f05c --- /dev/null +++ b/solid/control/networking.h @@ -0,0 +1,99 @@ +/* This file is part of the KDE project + Copyright (C) 2006-2007 Will Stephenson + Copyright (C) 2006-2007 Kevin Ottens + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#ifndef SOLID_CONTROL_NETWORKING_H +#define SOLID_CONTROL_NETWORKING_H + +#include + +#include "solid_control_export.h" +class QAbstractSocket; + +namespace Solid +{ +namespace Control +{ + /** + * This class allow to query the underlying system to discover the available + * network interfaces and reachable network.It has also the + * responsibility to notify when a network interface or a network appear or disappear. + * + * It's the unique entry point for network management. Applications should use + * it to find network interfaces, or to be notified about network related changes. + * + * Note that it's implemented as a singleton and encapsulates the backend logic. + */ + namespace Networking + { + /** + * Describe the result of a connection request + * - Accepted : the request was accepted and is being acted upon + * - AlreadyConnected : the system was already connected + * - Denied : the request was denied + */ + enum Result { Accepted, AlreadyConnected, Denied }; + + /** + * Magic network management for application's sockets. + * When the socket begins to connect it will automatically bring up + * networking, if not already available. + * When the network disconnects, optionally disconnects the socket early + * so that an application may continue. + * @param socket the socket to manage. + * @param autoDisconnectTimeout wait this many milliseconds after receiving a disconnected + * event from the networking subsystem before disconnecting the socket. A value of 0 means + * never automatically disconnect. + * @return whether the management request succeeded. + */ + SOLIDCONTROL_EXPORT Result beginManagingSocket( QAbstractSocket * socket, uint autoDisconnectTimeout = 0 ); + + /** + * Remove the socket from the list of sockets to manage. The socket's state is unaltered. + * @param socket the socket to stop managing. + */ + SOLIDCONTROL_EXPORT void stopManagingSocket( QAbstractSocket * socket ); + + /** + * Requests that the networking subsystem makes a connection. If an on-demand connection + * is started as a result of this request, the connection is refcounted and KDE's use of + * the connection is dropped when the last application uses it calls @ref + * releaseConnection(). + * Optionally, pass in a QObject and slot to call on it, to receive notification when the + * connection is available or not. The slot may take a Solid::Networking::Status to + * indicate success or failure. + * + * @param receiver the QObject to call a slot on. + * @param member the slot to call. + * @return a Result indication whether the request was accepted. + */ + SOLIDCONTROL_EXPORT Result requestConnection( QObject * receiver = 0, const char * member = 0 ); + + /** + * Activates or deactivates networking (as a whole). + * + * @param enabled true to activate networking, false otherwise + */ + SOLIDCONTROL_EXPORT void releaseConnection(); + } // Networking + +} // namespace Control +} // Solid + +#endif diff --git a/solid/control/networking_p.h b/solid/control/networking_p.h new file mode 100644 index 000000000..4b3694975 --- /dev/null +++ b/solid/control/networking_p.h @@ -0,0 +1,109 @@ +/* This file is part of the KDE project + Copyright (C) 2006-2007 Will Stephenson + Copyright (C) 2006-2007 Kevin Ottens + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ +#ifndef SOLID_CONTROL_NETWORKING_P_H +#define SOLID_CONTROL_NETWORKING_P_H + +#include + +#include + +#include "networking.h" + +class OrgKdeSolidNetworkingInterface; +class QAbstractSocket; +class QTimer; + + +namespace Solid +{ +namespace Control +{ + + class ManagedSocketContainer; + + class NetworkingPrivate : public QObject + { + Q_OBJECT + public: + NetworkingPrivate(); + ~NetworkingPrivate(); + Networking::Result beginManagingSocket( QAbstractSocket * socket, int autoDisconnectTimeout ); + void stopManagingSocket( QAbstractSocket * socket ); + public Q_SLOTS: + uint requestConnection( QObject* receiver = 0, const char * member = 0 ); /*Result*/ + void releaseConnection(); + Q_SIGNALS: + /** + * Indicates the result of the previous requestConnection() call + */ + void connectionResult( Solid::Networking::Status ); + private: + OrgKdeSolidNetworkingInterface * iface; + QMap mManagedSockets; + bool mNotifyConnectionResult; + }; + + /** + * ManagedSocketContainer manages a single socket's state in accordance + * with what the network management backend does. If it detects that the + * socket tries to connect and fails, it initiates a Networking connection, + * waits for the connection to come up, then connects the socket to its + * original host. + * + * STATE DIAGRAM + * + * Disconnected + * | + * (sock connecting) + * | + * V + * Connecting + * | + * ( TBD - currently exists on paper ) + */ + class ManagedSocketContainer : public QObject + { + Q_OBJECT + public: + enum State { SocketUnconnected, SocketConnecting, AwaitingNetworkConnection, SocketConnected, DisconnectWait }; + ManagedSocketContainer( QAbstractSocket * socket, int autoDisconnectTimeout = -1 ); + private Q_SLOTS: + // update our state and try to connect the socket if waiting for a connection + void networkStatusChanged( Solid::Networking::Status ); + // the socket errored, go to AwaitingConnection if offline + void socketError( QAbstractSocket::SocketError ); + // update our state and connect the socket if required + void socketStateChanged( QAbstractSocket::SocketState ); + // perform an automatic disconnect + void autoDisconnect(); + void socketDestroyed(); + private: + void performConnectToHost(); + QAbstractSocket * mSocket; + QTimer * mAutoDisconnectTimer; + uint mAutoDisconnectTimeout; + State mState; + QString mPeerName; + quint16 mPeerPort; + QIODevice::OpenMode mSocketOpenMode; + }; +} // namespace Control +} // namespace Solid +#endif diff --git a/solid/control/networkinterface.cpp b/solid/control/networkinterface.cpp new file mode 100644 index 000000000..97f5704e6 --- /dev/null +++ b/solid/control/networkinterface.cpp @@ -0,0 +1,122 @@ +/* This file is part of the KDE project + Copyright (C) 2006 Will Stephenson + Copyright (C) 2007 Kevin Ottens + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#include "networkinterface.h" +#include "networkinterface_p.h" + +#include "soliddefs_p.h" +#include "ifaces/networkinterface.h" + +Solid::Control::NetworkInterface::NetworkInterface(QObject *backendObject) + : QObject(), d_ptr(new NetworkInterfacePrivate(this)) +{ + Q_D(NetworkInterface); + d->setBackendObject(backendObject); +} + +Solid::Control::NetworkInterface::NetworkInterface(const NetworkInterface &other) + : QObject(), d_ptr(new NetworkInterfacePrivate(this)) +{ + Q_D(NetworkInterface); + d->setBackendObject(other.d_ptr->backendObject()); +} + +Solid::Control::NetworkInterface::NetworkInterface(NetworkInterfacePrivate &dd, QObject *backendObject) + : QObject(), d_ptr(&dd) +{ + Q_UNUSED(backendObject); +} + +Solid::Control::NetworkInterface::NetworkInterface(NetworkInterfacePrivate &dd, const NetworkInterface &other) + : d_ptr(&dd) +{ + Q_UNUSED(other); +} + +Solid::Control::NetworkInterface::~NetworkInterface() +{ + delete d_ptr; +} + +Solid::Control::NetworkInterface::Type Solid::Control::NetworkInterface::type() const +{ + return UnknownType; +} + +QString Solid::Control::NetworkInterface::uni() const +{ + Q_D(const NetworkInterface); + return_SOLID_CALL(Ifaces::NetworkInterface *, d->backendObject(), QString(), uni()); +} + +QString Solid::Control::NetworkInterface::interfaceName() const +{ + Q_D(const NetworkInterface); + return_SOLID_CALL(Ifaces::NetworkInterface *, d->backendObject(), QString(), interfaceName()); +} + +QString Solid::Control::NetworkInterface::driver() const +{ + Q_D(const NetworkInterface); + return_SOLID_CALL(Ifaces::NetworkInterface *, d->backendObject(), QString(), driver()); +} + +Solid::Control::IPv4Config Solid::Control::NetworkInterface::ipV4Config() const +{ + Q_D(const NetworkInterface); + return_SOLID_CALL(Ifaces::NetworkInterface *, d->backendObject(), Solid::Control::IPv4Config(), ipV4Config() ); +} + +bool Solid::Control::NetworkInterface::isActive() const +{ + Q_D(const NetworkInterface); + return_SOLID_CALL(Ifaces::NetworkInterface *, d->backendObject(), false, isActive()); +} + +Solid::Control::NetworkInterface::ConnectionState Solid::Control::NetworkInterface::connectionState() const +{ + Q_D(const NetworkInterface); + return_SOLID_CALL(Ifaces::NetworkInterface *, d->backendObject(), UnknownState, connectionState()); +} + +int Solid::Control::NetworkInterface::designSpeed() const +{ + Q_D(const NetworkInterface); + return_SOLID_CALL(Ifaces::NetworkInterface *, d->backendObject(), 0, designSpeed()); +} + +Solid::Control::NetworkInterface::Capabilities Solid::Control::NetworkInterface::capabilities() const +{ + Q_D(const NetworkInterface); + return_SOLID_CALL(Ifaces::NetworkInterface *, d->backendObject(), Capabilities(), capabilities()); +} + +void Solid::Control::NetworkInterfacePrivate::setBackendObject(QObject *object) +{ + FrontendObjectPrivate::setBackendObject(object); + + if (object) { + QObject::connect(object, SIGNAL(connectionStateChanged(int)), + parent(), SIGNAL(connectionStateChanged(int))); + } +} + + +#include "networkinterface.moc" diff --git a/solid/control/networkinterface.h b/solid/control/networkinterface.h new file mode 100644 index 000000000..9e7f1db7e --- /dev/null +++ b/solid/control/networkinterface.h @@ -0,0 +1,203 @@ +/* This file is part of the KDE project + Copyright (C) 2006 Will Stephenson + Copyright (C) 2007 Kevin Ottens + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#ifndef SOLID_CONTROL_NETWORKINTERFACE_H +#define SOLID_CONTROL_NETWORKINTERFACE_H + +#include +#include +#include + +#include "solid_control_export.h" + +#include "networkipv4config.h" + +namespace Solid +{ +namespace Control +{ + class NetworkInterfacePrivate; + + /** + * This interface represents a generic network interface in the system + */ + class SOLIDCONTROL_EXPORT NetworkInterface : public QObject + { + Q_OBJECT + Q_ENUMS(ConnectionState Capability Type) + Q_FLAGS(Capabilities) + Q_DECLARE_PRIVATE(NetworkInterface) + + public: + // == NM ActivationStage + /** + * Device connection states describe the possible states of a + * network connection from the user's point of view. For + * simplicity, states from several different layers are present - + * this is a high level view + */ + enum ConnectionState{ UnknownState, Unmanaged, Unavailable, Disconnected, Preparing, + Configuring, NeedAuth, IPConfig, Activated, Failed }; + /** + * Possible Device capabilities + * - IsManageable: denotes that the device can be controlled by this API + * - SupportsCarrierDetect: the device informs us when it is plugged in to the medium + * - SupportsWirelessScan: the device can scan for wireless networks + */ + enum Capability { IsManageable = 0x1, SupportsCarrierDetect = 0x2 }; + /** + * Device medium types + * - Ieee8023: wired ethernet + * - Ieee80211: the popular family of wireless networks + * - Gsm: cellular device of the GSM family, used in Europe + * - Cdma: cellular device of the CDMA family, used in the USA + */ + enum Type { UnknownType, Ieee8023, Ieee80211, Serial, Gsm, Cdma }; + + Q_DECLARE_FLAGS(Capabilities, Capability) + + /** + * Creates a new NetworkInterface object. + * + * @param backendObject the network object provided by the backend + */ + explicit NetworkInterface(QObject *backendObject); + + /** + * Constructs a copy of a network. + * + * @param network the network to copy + */ + NetworkInterface(const NetworkInterface &network); + + /** + * Destroys a NetworkInterface object. + */ + virtual ~NetworkInterface(); + + /** + * Retrieves the interface type. This is a virtual function that will return the + * proper type of all sub-classes. + * + * @returns the NetworkInterface::Type that corresponds to this device. + */ + virtual Type type() const; + + /** + * Retrieves the Unique Network Identifier (UNI) of the NetworkInterface. + * This identifier is unique for each network and network interface in the system. + * + * @returns the Unique Network Identifier of the current network + */ + QString uni() const; + + /** + * The system name for the network interface + */ + QString interfaceName() const; + + /** + * Handle for the system driver controlling this network interface + */ + QString driver() const; + + Solid::Control::IPv4Config ipV4Config() const; + /** + * Retrieves the activation status of this network interface. + * + * @return true if this network interface is active, false otherwise + */ + bool isActive() const; + + /** + * Retrieves the current state of the network connection held by this device. + * It's a high level view of the connection. It is user oriented, so + * actually it provides state coming from different layers. + * + * @return the current connection state + * @see Solid::Control::NetworkInterface::ConnectionState + */ + ConnectionState connectionState() const; + + /** + * Retrieves the maximum speed as reported by the device. + * Note that this is only a design related piece of information, and that + * the device might not reach this maximum. + * + * @return the device's maximum speed + */ + int designSpeed() const; + + /** + * Retrieves the capabilities supported by this device. + * + * @return the capabilities of the device + */ + Capabilities capabilities() const; + + Q_SIGNALS: + /** + * This signal is emitted when the settings of this network have changed. + */ + void ipDetailsChanged(); + + /** + * This signal is emitted when the device's link status changed. For example, if there + * is no carrier anymore. + * + * @param linkActivated true if the carrier got detected, false otherwise + */ + void linkUpChanged(bool linkActivated); + + /** + * This signal is emitted when the device's link status changed. For example, if there + * is no carrier anymore. + * + * @param state the new state of the connection + * @see Solid::Control::NetworkInterface::ConnectionState + */ + void connectionStateChanged(int state); + + protected: + /** + * @internal + */ + NetworkInterface(NetworkInterfacePrivate &dd, QObject *backendObject); + + /** + * @internal + */ + NetworkInterface(NetworkInterfacePrivate &dd, const NetworkInterface &network); + + NetworkInterfacePrivate *d_ptr; + + private: + //HACK: to make NetworkList polymorphic (containing both wired and wireless networks, I used Network * here - Will. + }; + typedef QList NetworkInterfaceList; + + +} //Control +} //Solid + +Q_DECLARE_OPERATORS_FOR_FLAGS(Solid::Control::NetworkInterface::Capabilities) + +#endif //SOLID_CONTROL_NETWORKINTERFACE_H + diff --git a/solid/control/networkinterface_p.h b/solid/control/networkinterface_p.h new file mode 100644 index 000000000..2b55bd376 --- /dev/null +++ b/solid/control/networkinterface_p.h @@ -0,0 +1,42 @@ +/* This file is part of the KDE project + Copyright (C) 2006 Will Stephenson + Copyright (C) 2007 Kevin Ottens + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#ifndef SOLID_NETWORKINTERFACE_P_H +#define SOLID_NETWORKINTERFACE_P_H + +#include "frontendobject_p.h" + +namespace Solid +{ +namespace Control +{ + class NetworkInterfacePrivate : public FrontendObjectPrivate + { + public: + explicit NetworkInterfacePrivate(QObject *parent) + : FrontendObjectPrivate(parent) { } + + void setBackendObject(QObject *object); + }; +} +} + +#endif //SOLID_NETWORKINTERFACE_P_H + diff --git a/solid/control/networkipv4config.cpp b/solid/control/networkipv4config.cpp new file mode 100644 index 000000000..45313a20d --- /dev/null +++ b/solid/control/networkipv4config.cpp @@ -0,0 +1,232 @@ +/* +Copyright 2008 Will Stephenson + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of +the License or (at your option) version 3 or any later version +accepted by the membership of KDE e.V. (or its successor approved +by the membership of KDE e.V.), which shall act as a proxy +defined in Section 14 of version 3 of the license. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +*/ + +#include "networkipv4config.h" + +namespace Solid +{ +namespace Control +{ +class IPv4Config::Private +{ +public: + Private(const QList &theAddresses, + const QList &theNameservers, + const QStringList &theDomains, const QList &theRoutes) + : addresses(theAddresses), nameservers(theNameservers), + domains(theDomains), routes(theRoutes) + {} + Private() + {} + QList addresses; + QList nameservers; + QStringList domains; + QList routes; +}; + + +class IPv4Address::Private +{ +public: + Private(quint32 theAddress, quint32 theNetMask, quint32 theGateway) + : address(theAddress), netMask(theNetMask), gateway(theGateway) + {} + Private() + : address(0), netMask(0), gateway(0) + {} + quint32 address; + quint32 netMask; + quint32 gateway; +}; + +class IPv4Route::Private +{ +public: + Private(quint32 theRoute, quint32 thePrefix, quint32 theNextHop, quint32 theMetric) + : route(theRoute), prefix(thePrefix), nextHop(theNextHop), metric(theMetric) + {} + Private() + : route(0), prefix(0), nextHop(0), metric(0) + {} + quint32 route; + quint32 prefix; + quint32 nextHop; + quint32 metric; +}; +} +} + +Solid::Control::IPv4Address::IPv4Address(quint32 address, quint32 netMask, quint32 gateway) +: d(new Private(address, netMask, gateway)) +{ +} + +Solid::Control::IPv4Address::IPv4Address() +: d(new Private()) +{ +} + +Solid::Control::IPv4Address::~IPv4Address() +{ + delete d; +} + +Solid::Control::IPv4Address::IPv4Address(const IPv4Address &other) +: d(new Private(*other.d)) +{ +} + +quint32 Solid::Control::IPv4Address::address() const +{ + return d->address; +} + +quint32 Solid::Control::IPv4Address::netMask() const +{ + return d->netMask; +} + +quint32 Solid::Control::IPv4Address::gateway() const +{ + return d->gateway; +} + +Solid::Control::IPv4Address &Solid::Control::IPv4Address::operator=(const Solid::Control::IPv4Address &other) +{ + if (this == &other) + return *this; + + *d = *other.d; + return *this; +} + +bool Solid::Control::IPv4Address::isValid() const +{ + return d->address != 0; +} + +Solid::Control::IPv4Route::IPv4Route(quint32 route, quint32 prefix, quint32 nextHop, quint32 metric) +: d(new Private(route, prefix, nextHop, metric)) +{ +} + +Solid::Control::IPv4Route::IPv4Route() +: d(new Private()) +{ +} + +Solid::Control::IPv4Route::~IPv4Route() +{ + delete d; +} + +Solid::Control::IPv4Route::IPv4Route(const IPv4Route &other) +: d(new Private(*other.d)) +{ +} + +quint32 Solid::Control::IPv4Route::route() const +{ + return d->route; +} + +quint32 Solid::Control::IPv4Route::prefix() const +{ + return d->prefix; +} + +quint32 Solid::Control::IPv4Route::nextHop() const +{ + return d->nextHop; +} + +quint32 Solid::Control::IPv4Route::metric() const +{ + return d->metric; +} + +Solid::Control::IPv4Route &Solid::Control::IPv4Route::operator=(const Solid::Control::IPv4Route &other) +{ + if (this == &other) + return *this; + + *d = *other.d; + return *this; +} + +bool Solid::Control::IPv4Route::isValid() const +{ + return d->route != 0; +} + + +Solid::Control::IPv4Config::IPv4Config(const QList &addresses, + const QList &nameservers, + const QStringList &domains, + const QList &routes) +: d(new Private(addresses, nameservers, domains, routes)) +{ +} + +Solid::Control::IPv4Config::IPv4Config() +: d(new Private()) +{ +} + +Solid::Control::IPv4Config::IPv4Config(const Solid::Control::IPv4Config& other) +{ + d = new Private(*other.d); +} + +Solid::Control::IPv4Config::~IPv4Config() +{ + delete d; +} + +QList Solid::Control::IPv4Config::addresses() const +{ + return d->addresses; +} + +QList Solid::Control::IPv4Config::nameservers() const +{ + return d->nameservers; +} + +QStringList Solid::Control::IPv4Config::domains() const +{ + return d->domains; +} + +Solid::Control::IPv4Config &Solid::Control::IPv4Config::operator=(const Solid::Control::IPv4Config& other) +{ + if (this == &other) + return *this; + + *d = *other.d; + return *this; +} + +bool Solid::Control::IPv4Config::isValid() const +{ + return !d->addresses.isEmpty(); +} + diff --git a/solid/control/networkipv4config.h b/solid/control/networkipv4config.h new file mode 100644 index 000000000..d9c6fc539 --- /dev/null +++ b/solid/control/networkipv4config.h @@ -0,0 +1,96 @@ +/* +* Copyright 2008 Will Stephenson + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of +the License or (at your option) version 3 or any later version +accepted by the membership of KDE e.V. (or its successor approved +by the membership of KDE e.V.), which shall act as a proxy +defined in Section 14 of version 3 of the license. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +*/ + +#ifndef SOLID_CONTROL_NETWORKIPV4CONFIG_H +#define SOLID_CONTROL_NETWORKIPV4CONFIG_H + +#include + +#include "solid_control_export.h" + +namespace Solid +{ +namespace Control +{ + +class SOLIDCONTROL_EXPORT IPv4Address +{ +public: + IPv4Address(quint32 address, quint32 netMask, quint32 gateway); + IPv4Address(); + ~IPv4Address(); + IPv4Address(const IPv4Address&); + quint32 address() const; + quint32 netMask() const; + quint32 gateway() const; + IPv4Address &operator=(const IPv4Address&); + bool isValid() const; +private: + class Private; + Private * d; +}; + +class SOLIDCONTROL_EXPORT IPv4Route +{ +public: + IPv4Route(quint32 route, quint32 prefix, quint32 nextHop, quint32 metric); + IPv4Route(); + ~IPv4Route(); + IPv4Route(const IPv4Route&); + IPv4Route &operator=(const IPv4Route&); + bool isValid() const; + quint32 route() const; + quint32 prefix() const; + quint32 nextHop() const; + quint32 metric() const; +private: + class Private; + Private * d; +}; + +class SOLIDCONTROL_EXPORT IPv4Config +{ +public: + IPv4Config(const QList &addresses, + const QList &nameservers, + const QStringList &domains, + const QList &routes); + IPv4Config(); + ~IPv4Config(); + IPv4Config(const IPv4Config&); + /** + * List of IP addresses related to this configuration. + */ + QList addresses() const; + QList nameservers() const; + QStringList domains() const; + QList routes() const; + IPv4Config &operator=(const IPv4Config&); + bool isValid() const; +private: + class Private; + Private * d; +}; + +} // namespace Control +} // namespace Solid + +#endif // NETWORKIPV4CONFIG_H diff --git a/solid/control/networkmanager.cpp b/solid/control/networkmanager.cpp new file mode 100644 index 000000000..3869bf8a3 --- /dev/null +++ b/solid/control/networkmanager.cpp @@ -0,0 +1,276 @@ +/* This file is part of the KDE project + Copyright (C) 2006 Will Stephenson + Copyright (C) 2006-2007 Kevin Ottens + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#include "ifaces/networkmanager.h" +#include "ifaces/networkinterface.h" +#include "ifaces/wirednetworkinterface.h" +#include "ifaces/wirelessnetworkinterface.h" +#include "ifaces/networkgsminterface.h" +#include "ifaces/networkcdmainterface.h" + +#include "soliddefs_p.h" +#include "networkmanager_p.h" +#include "networkinterface.h" +#include "wirednetworkinterface.h" +#include "wirelessnetworkinterface.h" + +#include "networkmanager.h" + +#include + +#include + +K_GLOBAL_STATIC(Solid::Control::NetworkManagerPrivate, globalNetworkManager) + +Solid::Control::NetworkManagerPrivate::NetworkManagerPrivate() : m_invalidDevice(0) +{ + loadBackend("Network Management", + "SolidNetworkManager", + "Solid::Control::Ifaces::NetworkManager"); + + if (managerBackend()!=0) { + connect(managerBackend(), SIGNAL(networkInterfaceAdded(const QString &)), + this, SLOT(_k_networkInterfaceAdded(const QString &))); + connect(managerBackend(), SIGNAL(networkInterfaceRemoved(const QString &)), + this, SLOT(_k_networkInterfaceRemoved(const QString &))); + connect(managerBackend(), SIGNAL(statusChanged(Solid::Networking::Status)), + this, SIGNAL(statusChanged(Solid::Networking::Status))); + connect(managerBackend(), SIGNAL(wirelessEnabledChanged(bool)), + this, SIGNAL(wirelessEnabledChanged(bool))); + connect(managerBackend(), SIGNAL(wirelessHardwareEnabledChanged(bool)), + this, SIGNAL(wirelessHardwareEnabledChanged(bool))); + connect(managerBackend(), SIGNAL(activeConnectionsChanged()), + this, SIGNAL(activeConnectionsChanged())); + } +} + +Solid::Control::NetworkManagerPrivate::~NetworkManagerPrivate() +{ + // Delete all the devices, they are now outdated + typedef QPair NetworkInterfaceIfacePair; + + foreach (const NetworkInterfaceIfacePair &pair, m_networkInterfaceMap) { + delete pair.first; + delete pair.second; + } + + m_networkInterfaceMap.clear(); +} + +Solid::Control::NetworkInterfaceList Solid::Control::NetworkManagerPrivate::buildDeviceList(const QStringList &uniList) +{ + NetworkInterfaceList list; + Ifaces::NetworkManager *backend = qobject_cast(managerBackend()); + + if (backend == 0) return list; + + foreach (const QString &uni, uniList) + { + QPair pair = findRegisteredNetworkInterface(uni); + + if (pair.first!= 0) + { + list.append(pair.first); + } + } + + return list; +} + +Solid::Control::NetworkInterfaceList Solid::Control::NetworkManagerPrivate::networkInterfaces() +{ + Ifaces::NetworkManager *backend = qobject_cast(managerBackend()); + + if (backend!= 0) + { + return buildDeviceList(backend->networkInterfaces()); + } + else + { + return NetworkInterfaceList(); + } +} + +Solid::Control::NetworkInterfaceList Solid::Control::NetworkManager::networkInterfaces() +{ + return globalNetworkManager->networkInterfaces(); +} + +bool Solid::Control::NetworkManager::isNetworkingEnabled() +{ + return_SOLID_CALL(Ifaces::NetworkManager *, globalNetworkManager->managerBackend(), false, isNetworkingEnabled()); +} + +bool Solid::Control::NetworkManager::isWirelessEnabled() +{ + return_SOLID_CALL(Ifaces::NetworkManager *, globalNetworkManager->managerBackend(), false, isWirelessEnabled()); +} + +bool Solid::Control::NetworkManager::isWirelessHardwareEnabled() +{ + return_SOLID_CALL(Ifaces::NetworkManager *, globalNetworkManager->managerBackend(), false, isWirelessHardwareEnabled()); +} + +void Solid::Control::NetworkManager::setNetworkingEnabled(bool enabled) +{ + SOLID_CALL(Ifaces::NetworkManager *, globalNetworkManager->managerBackend(), setNetworkingEnabled(enabled)); +} + +void Solid::Control::NetworkManager::setWirelessEnabled(bool enabled) +{ + SOLID_CALL(Ifaces::NetworkManager *, globalNetworkManager->managerBackend(), setWirelessEnabled(enabled)); +} + +Solid::Networking::Status Solid::Control::NetworkManager::status() +{ + return_SOLID_CALL(Ifaces::NetworkManager *, globalNetworkManager->managerBackend(), Solid::Networking::Unknown, status()); +} + +Solid::Control::NetworkInterface * Solid::Control::NetworkManagerPrivate::findNetworkInterface(const QString &uni) +{ + Ifaces::NetworkManager *backend = qobject_cast(managerBackend()); + + if (backend == 0) return 0; + + QPair pair = findRegisteredNetworkInterface(uni); + + if (pair.first != 0) + { + return pair.first; + } + else + { + return 0; + } +} + +Solid::Control::NetworkInterface * Solid::Control::NetworkManager::findNetworkInterface(const QString &uni) +{ + return globalNetworkManager->findNetworkInterface(uni); +} + +Solid::Control::NetworkManager::Notifier * Solid::Control::NetworkManager::notifier() +{ + return globalNetworkManager; +} + +void Solid::Control::NetworkManagerPrivate::_k_networkInterfaceAdded(const QString &uni) +{ + QPair pair = m_networkInterfaceMap.take(uni); + + if (pair.first!= 0) + { + // Oops, I'm not sure it should happen... + // But well in this case we'd better kill the old device we got, it's probably outdated + + delete pair.first; + delete pair.second; + } + + emit networkInterfaceAdded(uni); +} + +void Solid::Control::NetworkManagerPrivate::_k_networkInterfaceRemoved(const QString &uni) +{ + QPair pair = m_networkInterfaceMap.take(uni); + + if (pair.first!= 0) + { + delete pair.first; + delete pair.second; + } + + emit networkInterfaceRemoved(uni); +} + +void Solid::Control::NetworkManagerPrivate::_k_destroyed(QObject *object) +{ + Ifaces::NetworkInterface *device = qobject_cast(object); + + if (device!=0) + { + QString uni = device->uni(); + QPair pair = m_networkInterfaceMap.take(uni); + delete pair.first; + } +} + +/***************************************************************************/ + +QPair +Solid::Control::NetworkManagerPrivate::findRegisteredNetworkInterface(const QString &uni) +{ + if (m_networkInterfaceMap.contains(uni)) { + return m_networkInterfaceMap[uni]; + } else { + Ifaces::NetworkManager *backend = qobject_cast(managerBackend()); + + if (backend!=0) + { + QObject * iface = backend->createNetworkInterface(uni); + NetworkInterface *device = 0; + if (qobject_cast(iface) != 0) { + device = new WirelessNetworkInterface(iface); + } else if (qobject_cast(iface) != 0) { + device = new WiredNetworkInterface(iface); + } else if (qobject_cast(iface) != 0) { + device = new GsmNetworkInterface(iface); + } else if (qobject_cast(iface) != 0) { + device = new CdmaNetworkInterface(iface); + } else { + kDebug() << "Unhandled network interface: " << uni; + } + if (device != 0) { + QPair pair(device, iface); + connect(iface, SIGNAL(destroyed(QObject *)), + this, SLOT(_k_destroyed(QObject *))); + m_networkInterfaceMap[uni] = pair; + return pair; + } + else + { + return QPair(0, 0); + } + } + else + { + return QPair(0, 0); + } + } +} + +void Solid::Control::NetworkManager::activateConnection(const QString & interfaceUni, const QString & connectionUni, + const QVariantMap & connectionParameters ) +{ + SOLID_CALL(Ifaces::NetworkManager *, globalNetworkManager->managerBackend(), activateConnection(interfaceUni, connectionUni, connectionParameters)); +} + +void Solid::Control::NetworkManager::deactivateConnection(const QString & activeConnectionUni) +{ + SOLID_CALL(Ifaces::NetworkManager *, globalNetworkManager->managerBackend(), deactivateConnection(activeConnectionUni)); +} + +QStringList Solid::Control::NetworkManager::activeConnections() +{ + return_SOLID_CALL(Ifaces::NetworkManager *, globalNetworkManager->managerBackend(), QStringList(), activeConnections()); +} + +#include "networkmanager_p.moc" +#include "networkmanager.moc" diff --git a/solid/control/networkmanager.h b/solid/control/networkmanager.h new file mode 100644 index 000000000..6b7c4137b --- /dev/null +++ b/solid/control/networkmanager.h @@ -0,0 +1,175 @@ +/* This file is part of the KDE project + Copyright (C) 2006 Will Stephenson + Copyright (C) 2006-2007 Kevin Ottens + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#ifndef SOLID_CONTROL_NETWORKMANAGER +#define SOLID_CONTROL_NETWORKMANAGER + +#include +#include + +#include +#include "solid_control_export.h" + +namespace Solid +{ +namespace Control +{ + namespace Ifaces + { + class NetworkManager; + } + class Network; + class NetworkInterface; + typedef QList NetworkInterfaceList; + + /** + * This class allow to query the underlying system to discover the available + * network interfaces and reachable network.It has also the + * responsibility to notify when a network interface or a network appear or disappear. + * + * It's the unique entry point for network management. Applications should use + * it to find network interfaces, or to be notified about network related changes. + * + * Note that it's implemented as a singleton and encapsulates the backend logic. + */ + namespace NetworkManager + { + /** + * Get the manager connection state + */ + SOLIDCONTROL_EXPORT Solid::Networking::Status status(); + /** + * Retrieves the list of all the network interfaces in the system. + * It includes both hardware and virtual devices. + * + * @return the list of network interfaces available in this system + */ + SOLIDCONTROL_EXPORT NetworkInterfaceList networkInterfaces(); + + /** + * Find a new NetworkInterface object given its UNI. This pointer is owned by the Solid + * infrastructure. + * + * @param uni the identifier of the network interface to find + * @returns a valid NetworkInterface object if there's a device having the given UNI, an invalid one otherwise + */ + SOLIDCONTROL_EXPORT NetworkInterface * findNetworkInterface(const QString &uni); + + /** + * Retrieves the status of networking (as a whole) in the system. + * This is distinct from whether the system's networking is online or offline. + * To check that, see @ref NetworkStatus. + * + * @return true if this networking is enabled, false otherwise + */ + SOLIDCONTROL_EXPORT bool isNetworkingEnabled(); + + /** + * Retrieves the activation status of wireless networking in the system. + * + * @return true if this wireless networking is enabled, false otherwise + */ + SOLIDCONTROL_EXPORT bool isWirelessEnabled(); + + + /** + * Activates or deactivates networking (as a whole). + * + * @param enabled true to activate networking, false otherwise + */ + SOLIDCONTROL_EXPORT void setNetworkingEnabled(bool enabled); + + /** + * Retrieves the status of wireless hardware in the system. This is typically + * controlled by a physical switch so there is no way to set this in software. + * + * @since KDE 4.1 + * @return true if this wireless networking is enabled, false otherwise + */ + SOLIDCONTROL_EXPORT bool isWirelessHardwareEnabled(); + + /** + * Activates or deactivates wireless networking. + * + * @param enabled true to activate wireless networking, false otherwise + */ + SOLIDCONTROL_EXPORT void setWirelessEnabled(bool enabled); + + /** + * @param deviceUni unique identifier of the network interface to be activated + * @param connectionUni unique identifier for the connection to be activated + * @param connectionParameters can be used to specify extra parameters not specific to the NetworkInterface or the connection, eg which AP to use when several present with same ESSID in range (because ESSID no guarantee that the AP is part of the network you want to join!) + * + */ + SOLIDCONTROL_EXPORT void activateConnection(const QString & deviceUni, const QString & connectionUni, + const QVariantMap & connectionParameters ); + /** + * Deactivate this network interface, if active + * @param activeConnectionUni identifer of the connection to deactivate + */ + SOLIDCONTROL_EXPORT void deactivateConnection(const QString & activeConnectionUni); + + /** + * Access the list of any active connections + */ + QStringList SOLIDCONTROL_EXPORT activeConnections(); + + class SOLIDCONTROL_EXPORT Notifier : public QObject + { + Q_OBJECT + Q_SIGNALS: + /** + * This signal is emitted when the system's connection state changes + */ + void statusChanged(Solid::Networking::Status status); + /** + * This signal is emitted when a new network interface is available. + * + * @param uni the network interface identifier + */ + void networkInterfaceAdded(const QString &uni); + + /** + * This signal is emitted when a network interface is not available anymore. + * + * @param uni the network interface identifier + */ + void networkInterfaceRemoved(const QString &uni); + /** + * This signal is emitted when the status of the wireless changed + */ + void wirelessEnabledChanged(bool enabled); + /** + * This signal is emitted when the status of the wireless hardware changed + */ + void wirelessHardwareEnabledChanged(bool enabled); + /** + * This signal is emitted when the set of active connections changes + */ + void activeConnectionsChanged(); + }; + + SOLIDCONTROL_EXPORT Notifier *notifier(); + } + +} // Control +} // Solid + +#endif diff --git a/solid/control/networkmanager_p.h b/solid/control/networkmanager_p.h new file mode 100644 index 000000000..98081aae3 --- /dev/null +++ b/solid/control/networkmanager_p.h @@ -0,0 +1,66 @@ +/* This file is part of the KDE project + Copyright (C) 2006 Will Stephenson + Copyright (C) 2006-2007 Kevin Ottens + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ +#ifndef SOLID_NETWORKMANAGER_P_H +#define SOLID_NETWORKMANAGER_P_H + +#include +#include +#include + +#include "managerbase_p.h" + +#include "networkmanager.h" +#include "networkinterface.h" + +namespace Solid +{ +namespace Control +{ + namespace Ifaces + { + class NetworkInterface; + } + + class NetworkManagerPrivate : public NetworkManager::Notifier, public ManagerBasePrivate + { + Q_OBJECT + public: + NetworkManagerPrivate(); + ~NetworkManagerPrivate(); + + NetworkInterfaceList networkInterfaces(); + NetworkInterface *findNetworkInterface(const QString &uni); + + private Q_SLOTS: + void _k_networkInterfaceAdded(const QString &uni); + void _k_networkInterfaceRemoved(const QString &uni); + void _k_destroyed(QObject *object); + + private: + NetworkInterfaceList buildDeviceList(const QStringList &uniList); + QPair findRegisteredNetworkInterface(const QString &uni); + + QMap > m_networkInterfaceMap; + NetworkInterface m_invalidDevice; + }; +} +} + +#endif diff --git a/solid/control/networkserialinterface.cpp b/solid/control/networkserialinterface.cpp new file mode 100644 index 000000000..2ccc601d9 --- /dev/null +++ b/solid/control/networkserialinterface.cpp @@ -0,0 +1,80 @@ +/* +Copyright 2008 Will Stephenson + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) version 3, or any +later version accepted by the membership of KDE e.V. (or its +successor approved by the membership of KDE e.V.), which shall +act as a proxy defined in Section 6 of version 3 of the license. + +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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library. If not, see . +*/ + +#include "networkserialinterface.h" +#include "networkserialinterface_p.h" + +#include "frontendobject_p.h" +#include "soliddefs_p.h" +#include "ifaces/wirelessaccesspoint.h" + +Solid::Control::SerialNetworkInterface::SerialNetworkInterface(QObject *backendObject) + : NetworkInterface(*new SerialNetworkInterfacePrivate(this), backendObject) +{ + Q_D(SerialNetworkInterface); + d->setBackendObject(backendObject); + makeConnections( backendObject ); +} + +Solid::Control::SerialNetworkInterface::SerialNetworkInterface(const SerialNetworkInterface &networkinterface) + : NetworkInterface(*new SerialNetworkInterfacePrivate(this), networkinterface) +{ + Q_D(SerialNetworkInterface); + d->setBackendObject(networkinterface.d_ptr->backendObject()); + makeConnections( networkinterface.d_ptr->backendObject() ); +} + +Solid::Control::SerialNetworkInterface::SerialNetworkInterface(SerialNetworkInterfacePrivate &dd, QObject *backendObject) + : NetworkInterface(dd, backendObject) +{ + makeConnections( backendObject ); +} + +Solid::Control::SerialNetworkInterface::SerialNetworkInterface(SerialNetworkInterfacePrivate &dd, const SerialNetworkInterface &networkinterface) + : NetworkInterface(dd, networkinterface.d_ptr->backendObject()) +{ + makeConnections( networkinterface.d_ptr->backendObject() ); +} + +Solid::Control::SerialNetworkInterface::~SerialNetworkInterface() +{ +} + +Solid::Control::NetworkInterface::Type Solid::Control::SerialNetworkInterface::type() const +{ + return Serial; +} + +void Solid::Control::SerialNetworkInterface::makeConnections(QObject * source) +{ + connect(source, SIGNAL(pppStats(uint,uint)), + this, SIGNAL(pppStats(uint,uint))); +} + +void Solid::Control::SerialNetworkInterfacePrivate::setBackendObject(QObject *object) +{ + NetworkInterfacePrivate::setBackendObject(object); +} + +void Solid::Control::SerialNetworkInterface::_k_destroyed(QObject *object) +{ + Q_UNUSED(object); +} +// vim: sw=4 sts=4 et tw=100 diff --git a/solid/control/networkserialinterface.h b/solid/control/networkserialinterface.h new file mode 100644 index 000000000..0525cbb97 --- /dev/null +++ b/solid/control/networkserialinterface.h @@ -0,0 +1,90 @@ +/* +Copyright 2008 Will Stephenson + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) version 3, or any +later version accepted by the membership of KDE e.V. (or its +successor approved by the membership of KDE e.V.), which shall +act as a proxy defined in Section 6 of version 3 of the license. + +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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library. If not, see . +*/ + +#ifndef SOLID_CONTROL_SERIALNETWORKINTERFACE_H +#define SOLID_CONTROL_SERIALNETWORKINTERFACE_H + +#include "networkinterface.h" + +namespace Solid +{ +namespace Control +{ + class SerialNetworkInterfacePrivate; + /** + * This interface represents a SERIAL cellular network interface + */ + class SOLIDCONTROL_EXPORT SerialNetworkInterface : public NetworkInterface + { + Q_OBJECT + Q_DECLARE_PRIVATE(SerialNetworkInterface) + + public: + /** + * Creates a new SerialNetworkInterface object. + * + * @param backendObject the network object provided by the backend + */ + SerialNetworkInterface(QObject *backendObject = 0); + + /** + * Constructs a copy of a network. + * + * @param network the network to copy + */ + SerialNetworkInterface(const SerialNetworkInterface &network); + + /** + * Destroys a SerialNetworkInterface object. + */ + virtual ~SerialNetworkInterface(); + + /** + * The NetworkInterface type. + * + * @return the NetworkInterface::Type. This always returns NetworkInterface::Ieee8023 + */ + virtual NetworkInterface::Type type() const; + + Q_SIGNALS: + void pppStats(uint in, uint out); + protected: + /** + * @internal + */ + SerialNetworkInterface(SerialNetworkInterfacePrivate &dd, QObject *backendObject); + + /** + * @internal + */ + SerialNetworkInterface(SerialNetworkInterfacePrivate &dd, const SerialNetworkInterface &network); + + void makeConnections(QObject * source); + private Q_SLOTS: + void _k_destroyed(QObject *object); + private: + friend class NetworkInterface; + friend class NetworkInterfacePrivate; + }; +} //Control +} //Solid + +#endif // SOLID_CONTROL_SERIALNETWORKINTERFACE_H + diff --git a/solid/control/networkserialinterface_p.h b/solid/control/networkserialinterface_p.h new file mode 100644 index 000000000..e66d66dc0 --- /dev/null +++ b/solid/control/networkserialinterface_p.h @@ -0,0 +1,41 @@ +/* +Copyright 2008 Will Stephenson + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) version 3, or any +later version accepted by the membership of KDE e.V. (or its +successor approved by the membership of KDE e.V.), which shall +act as a proxy defined in Section 6 of version 3 of the license. + +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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library. If not, see . +*/ + +#ifndef SOLID_CONTROL_SERIALNETWORKINTERFACE_P_H +#define SOLID_CONTROL_SERIALNETWORKINTERFACE_P_H + +#include "networkinterface_p.h" + +namespace Solid +{ +namespace Control +{ + class SerialNetworkInterfacePrivate : public NetworkInterfacePrivate + { + public: + explicit SerialNetworkInterfacePrivate(QObject *parent) + : NetworkInterfacePrivate(parent) { } + + void setBackendObject(QObject *object); + }; +} +} + +#endif //SOLID_CONTROL_SERIALNETWORKINTERFACE_P_H diff --git a/solid/control/org.kde.Solid.Networking.xml b/solid/control/org.kde.Solid.Networking.xml new file mode 100644 index 000000000..7371c9b64 --- /dev/null +++ b/solid/control/org.kde.Solid.Networking.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/solid/control/powermanager.cpp b/solid/control/powermanager.cpp new file mode 100644 index 000000000..8f947bf38 --- /dev/null +++ b/solid/control/powermanager.cpp @@ -0,0 +1,197 @@ +/* This file is part of the KDE project + Copyright (C) 2006-2007 Kevin Ottens + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#include "powermanager.h" +#include "powermanager_p.h" + +#include "soliddefs_p.h" +#include "managerbase_p.h" +#include "ifaces/powermanager.h" + +#include + +K_GLOBAL_STATIC(Solid::Control::PowerManagerPrivate, globalPowerManager) + +Solid::Control::PowerManagerPrivate::PowerManagerPrivate() +{ + loadBackend("Power Management", "SolidPowerManager", "Solid::Control::Ifaces::PowerManager"); + + if (managerBackend()!=0) { + connect(managerBackend(), SIGNAL(schemeChanged(QString)), + this, SIGNAL(schemeChanged(QString))); + connect(managerBackend(), SIGNAL(acAdapterStateChanged(int)), + this, SIGNAL(acAdapterStateChanged(int))); + connect(managerBackend(), SIGNAL(batteryStateChanged(int)), + this, SIGNAL(batteryStateChanged(int))); + connect(managerBackend(), SIGNAL(buttonPressed(int)), + this, SIGNAL(buttonPressed(int))); + connect(managerBackend(), SIGNAL(brightnessChanged(float)), + this, SIGNAL(brightnessChanged(float))); + } +} + +Solid::Control::PowerManagerPrivate::~PowerManagerPrivate() +{ +} + +QStringList Solid::Control::PowerManager::supportedSchemes() +{ + return_SOLID_CALL(Ifaces::PowerManager *, globalPowerManager->managerBackend(), + QStringList(), supportedSchemes()); +} + +QString Solid::Control::PowerManager::schemeDescription(const QString &schemeName) +{ + return_SOLID_CALL(Ifaces::PowerManager *, globalPowerManager->managerBackend(), + QString(), schemeDescription(schemeName)); +} + +QString Solid::Control::PowerManager::scheme() +{ + return_SOLID_CALL(Ifaces::PowerManager *, globalPowerManager->managerBackend(), QString(), scheme()); +} + +bool Solid::Control::PowerManager::setScheme(const QString &name) +{ + return_SOLID_CALL(Ifaces::PowerManager *, globalPowerManager->managerBackend(), + false, setScheme(name)); +} + +Solid::Control::PowerManager::BatteryState Solid::Control::PowerManager::batteryState() +{ + return_SOLID_CALL(Ifaces::PowerManager *, globalPowerManager->managerBackend(), + NoBatteryState, batteryState()); +} + +int Solid::Control::PowerManager::batteryChargePercent() +{ + return_SOLID_CALL(Ifaces::PowerManager *, globalPowerManager->managerBackend(), + -1, batteryChargePercent()); +} + +Solid::Control::PowerManager::AcAdapterState Solid::Control::PowerManager::acAdapterState() +{ + return_SOLID_CALL(Ifaces::PowerManager *, globalPowerManager->managerBackend(), + Plugged, acAdapterState()); +} + +Solid::Control::PowerManager::SuspendMethods Solid::Control::PowerManager::supportedSuspendMethods() +{ + return_SOLID_CALL(Ifaces::PowerManager *, globalPowerManager->managerBackend(), + UnknownSuspendMethod, supportedSuspendMethods()); +} + +KJob *Solid::Control::PowerManager::suspend(SuspendMethod method) +{ + return_SOLID_CALL(Ifaces::PowerManager *, globalPowerManager->managerBackend(), + 0, suspend(method)); +} + +Solid::Control::PowerManager::CpuFreqPolicies Solid::Control::PowerManager::supportedCpuFreqPolicies() +{ + return_SOLID_CALL(Ifaces::PowerManager *, globalPowerManager->managerBackend(), + UnknownCpuFreqPolicy, supportedCpuFreqPolicies()); +} + +Solid::Control::PowerManager::CpuFreqPolicy Solid::Control::PowerManager::cpuFreqPolicy() +{ + return_SOLID_CALL(Ifaces::PowerManager *, globalPowerManager->managerBackend(), + UnknownCpuFreqPolicy, cpuFreqPolicy()); +} + +bool Solid::Control::PowerManager::setCpuFreqPolicy(CpuFreqPolicy newPolicy) +{ + return_SOLID_CALL(Ifaces::PowerManager *, globalPowerManager->managerBackend(), + false, setCpuFreqPolicy(newPolicy)); +} + +bool Solid::Control::PowerManager::canDisableCpu(int cpuNum) +{ + return_SOLID_CALL(Ifaces::PowerManager *, globalPowerManager->managerBackend(), + false, canDisableCpu(cpuNum)); +} + +bool Solid::Control::PowerManager::setCpuEnabled(int cpuNum, bool enabled) +{ + return_SOLID_CALL(Ifaces::PowerManager *, globalPowerManager->managerBackend(), + false, setCpuEnabled(cpuNum, enabled)); +} + +Solid::Control::PowerManager::BrightnessControlsList Solid::Control::PowerManager::brightnessControlsAvailable() +{ + return_SOLID_CALL(Ifaces::PowerManager *, globalPowerManager->managerBackend(), + Solid::Control::PowerManager::BrightnessControlsList(), brightnessControlsAvailable()); +} + +bool Solid::Control::PowerManager::setBrightness(float brightness, const QString &device) +{ + if(device.isEmpty()) + { + Solid::Control::PowerManager::BrightnessControlsList controls = brightnessControlsAvailable(); + if(controls.size() == 0) + { + return false; + } + else + { + foreach(const QString &device, controls.keys()) + { + SOLID_CALL(Ifaces::PowerManager *, globalPowerManager->managerBackend(), setBrightness(brightness, device)); + } + //TODO - This should be done better, it will return true even if one of the calls returns false. SOLID_CALL does not allow us to get the return value. + return true; + } + } + else + { + return_SOLID_CALL(Ifaces::PowerManager *, globalPowerManager->managerBackend(), + false, setBrightness(brightness, device)); + } +} + +float Solid::Control::PowerManager::brightness(const QString &device) +{ + if(device.isEmpty()) + { + Solid::Control::PowerManager::BrightnessControlsList controls = brightnessControlsAvailable(); + if(controls.size() == 0) + { + return false; + } + else + { + return_SOLID_CALL(Ifaces::PowerManager *, globalPowerManager->managerBackend(), + false, brightness(controls.keys().at(0))); + } + } + else + { + return_SOLID_CALL(Ifaces::PowerManager *, globalPowerManager->managerBackend(), + false, brightness(device)); + } +} + +Solid::Control::PowerManager::Notifier *Solid::Control::PowerManager::notifier() +{ + return globalPowerManager; +} + +#include "powermanager_p.moc" +#include "powermanager.moc" + diff --git a/solid/control/powermanager.h b/solid/control/powermanager.h new file mode 100644 index 000000000..eea32b264 --- /dev/null +++ b/solid/control/powermanager.h @@ -0,0 +1,314 @@ +/* This file is part of the KDE project + Copyright (C) 2006-2007 Kevin Ottens + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#ifndef SOLID_CONTROL_POWERMANAGER_H +#define SOLID_CONTROL_POWERMANAGER_H + +#include +#include + +#include "solid_control_export.h" + +class KJob; + +namespace Solid +{ +namespace Control +{ + /** + * This namespace allows to query the underlying system to obtain information + * about the hardware available. + * + * It's the unique entry point for power management. Applications should use + * it to control or query the power management features of the system. + * + * Note that it's implemented as a singleton and encapsulates the backend logic. + * + * @author Kevin Ottens + */ + namespace PowerManager + { + /** + * This enum type defines the different states of the system battery. + * + * - NoBatteryState: No battery available + * - Normal: The battery is at its normal charge level + * - Warning: The battery is at its warning charge level + * - Low: The battery is at its low charge level + * - Critical: The battery is at its critical charge level + */ + enum BatteryState{ NoBatteryState, Normal, Warning, Low, Critical }; + + /** + * This enum type defines the different states of the AC adapter. + * + * - UnknownAcAdapterState: The AC adapter has an unknown state + * - Plugged: The AC adapter is plugged + * - Unplugged: The AC adapter is unplugged + */ + enum AcAdapterState{ UnknownAcAdapterState, Plugged, Unplugged }; + + /** + * This enum type defines the types of system button events. + * + * - UnknownButtonType: An unknown button + * - PowerButton: A power button pressed event, generally used to turn on or off the system + * - SleepButton: A sleep button pressed event, generally used to make the system asleep + * - LidOpen: A laptop lid open event + * - LidClose: A laptop lid close event + */ + enum ButtonType{ UnknownButtonType, PowerButton, SleepButton, LidOpen, LidClose }; + + /** + * This enum type defines the different suspend methods. + * + * - UnknownSuspendMethod: The name says it all + * - Standby: Processes are stopped, some hardware is deactivated (ACPI S1) + * - ToRam: Most devices are deactivated, only RAM is powered (ACPI S3) + * - ToDisk: State of the machine is saved to disk, and it's powered down (ACPI S4) + */ + enum SuspendMethod{ UnknownSuspendMethod = 0, Standby = 1, ToRam = 2, ToDisk = 4}; + + /** + * This type stores an OR combination of SuspendMethod values. + */ + Q_DECLARE_FLAGS(SuspendMethods, SuspendMethod) + + /** + * This enum type defines the different CPU frequency policies. + * + * - UnknownCpuFreqPolicy: The name says it all + * - OnDemand: Frequency is changed by the kernel depending on the processor load + * - Conservative: Frequency is changed by the kernel depending on the processor load; the stepping is less aggressive than OnDemand. This may be equivalent to OnDemand depending on the operating system. + * - Userspace: Frequency is changed by a userspace agent depending on the processor load + * - Powersave: Frequency is always set to the lowest available + * - Performance: Frequency is always set to the highest available + */ + enum CpuFreqPolicy{ UnknownCpuFreqPolicy = 0, OnDemand = 1, Userspace = 2, Powersave = 4, Performance = 8, Conservative = 16 }; + + /** + * This type stores an OR combination of CpuFreqPolicy values. + */ + Q_DECLARE_FLAGS(CpuFreqPolicies, CpuFreqPolicy) + + /** + * This enum defines the different types of brightness controls. + * + * - UnknownBrightnessControl: Unknown + * - Screen: Brightness control for a monitor or laptop panel + * - Keyboard: Brightness control for a keyboard backlight + */ + enum BrightnessControlType{ UnknownBrightnessControl = 0, Screen = 1, Keyboard = 2 }; + + typedef QHash BrightnessControlsList; + + + /** + * Retrieves the list of power management schemes available on this system. + * + * @return the available power management schemes + */ + SOLIDCONTROL_EXPORT QStringList supportedSchemes(); + + /** + * Retrieves a localized description corresponding to the given scheme. + * + * @param schemeName the name of the scheme we request the description for + * @return the associated description + */ + SOLIDCONTROL_EXPORT QString schemeDescription(const QString &schemeName); + + /** + * Retrieves the name of the current power management scheme used + * by the system. + * + * @return the current scheme + */ + SOLIDCONTROL_EXPORT QString scheme(); + + /** + * Changes the current power management scheme. + * + * @param name the name of the new scheme + * @return true if the scheme change succeeded, false otherwise + */ + SOLIDCONTROL_EXPORT bool setScheme(const QString &name); + + + /** + * Retrieves the current state of the system battery. + * + * @return the current battery state + * @see Solid::Control::PowerManager::BatteryState + */ + SOLIDCONTROL_EXPORT BatteryState batteryState(); + + /** + * Retrieves the current charge percentage of the system batteries. + * + * @return the current global battery charge percentage + */ + SOLIDCONTROL_EXPORT int batteryChargePercent(); + + /** + * Retrieves the current state of the system AC adapter. + * + * @return the current AC adapter state + * @see Solid::Control::PowerManager::AcAdapterState + */ + SOLIDCONTROL_EXPORT AcAdapterState acAdapterState(); + + + /** + * Retrieves the set of suspend methods supported by the system. + * + * @return the suspend methods supported by this system + * @see Solid::Control::PowerManager::SuspendMethod + * @see Solid::Control::PowerManager::SuspendMethods + */ + SOLIDCONTROL_EXPORT SuspendMethods supportedSuspendMethods(); + + /** + * Requests a suspend of the system. + * + * @param method the suspend method to use + * @return the job handling the operation + */ + SOLIDCONTROL_EXPORT KJob *suspend(SuspendMethod method); + + + /** + * Retrieves the set of CPU frequency policies supported by the system. + * + * @return the CPU frequency policies supported by this system + * @see Solid::Control::PowerManager::CpuFreqPolicy + * @see Solid::Control::PowerManager::CpuFreqPolicies + */ + SOLIDCONTROL_EXPORT CpuFreqPolicies supportedCpuFreqPolicies(); + + /** + * Retrieves the current CPU frequency policy of the system. + * + * @return the current CPU frequency policy used by the system + * @see Solid::Control::PowerManager::CpuFreqPolicy + */ + SOLIDCONTROL_EXPORT CpuFreqPolicy cpuFreqPolicy(); + + /** + * Changes the current CPU frequency policy of the system. + * + * @param newPolicy the new policy + * @return true if the policy change succeeded, false otherwise + * @see Solid::Control::PowerManager::CpuFreqPolicy + */ + SOLIDCONTROL_EXPORT bool setCpuFreqPolicy(CpuFreqPolicy newPolicy); + + /** + * Checks if a CPU can be disabled. + * + * @param cpuNum the number of the CPU we want to check + * @return true if the given CPU can be disabled, false otherwise + */ + SOLIDCONTROL_EXPORT bool canDisableCpu(int cpuNum); + + /** + * Enables or disables a CPU. + * + * @param cpuNum the number of the CPU we want to enable or disable + * @param enabled the new state of the CPU + * @return true if the state change succeeded, false otherwise + */ + SOLIDCONTROL_EXPORT bool setCpuEnabled(int cpuNum, bool enabled); + + /** + * Checks if brightness controls are enabled on this system. + * + * @return a list of the devices available to control + */ + SOLIDCONTROL_EXPORT BrightnessControlsList brightnessControlsAvailable(); + + /** + * Gets the screen brightness. + * + * @param device the name of the device that you would like to control + * @return the brightness of the device, as a percentage + */ + SOLIDCONTROL_EXPORT float brightness(const QString &device = QString()); + + /** + * Sets the screen brightness. + * + * @param brightness the desired screen brightness, as a percentage + * @param device the name of the device that you would like to control + * @return true if the brightness change succeeded, false otherwise + */ + SOLIDCONTROL_EXPORT bool setBrightness(float brightness, const QString &device = QString()); + + class SOLIDCONTROL_EXPORT Notifier : public QObject + { + Q_OBJECT + Q_SIGNALS: + /** + * This signal is emitted when the power management scheme has changed. + * + * @param newScheme the new scheme name + */ + void schemeChanged(QString newScheme); + + /** + * This signal is emitted when the AC adapter is plugged or unplugged. + * + * @param newState the new state of the AC adapter, it's one of the + * type @see Solid::Control::PowerManager::AcAdapterState + */ + void acAdapterStateChanged(int newState); + + /** + * This signal is emitted when the system battery state changed. + * + * @param newState the new state of the system battery, it's one of the + * type @see Solid::Control::PowerManager::BatteryState + */ + void batteryStateChanged(int newState); + + /** + * This signal is emitted when a button has been pressed. + * + * @param buttonType the pressed button type, it's one of the + * type @see Solid::Control::PowerManager::ButtonType + */ + void buttonPressed(int buttonType); + + /** + * This signal is emitted when the brightness changes. + * + * @param brightness the new brightness level + */ + void brightnessChanged(float brightness); + }; + + SOLIDCONTROL_EXPORT Notifier *notifier(); + } +} +} + +Q_DECLARE_OPERATORS_FOR_FLAGS(Solid::Control::PowerManager::SuspendMethods) +Q_DECLARE_OPERATORS_FOR_FLAGS(Solid::Control::PowerManager::CpuFreqPolicies) + +#endif diff --git a/solid/control/powermanager_p.h b/solid/control/powermanager_p.h new file mode 100644 index 000000000..d2439d010 --- /dev/null +++ b/solid/control/powermanager_p.h @@ -0,0 +1,41 @@ +/* This file is part of the KDE project + Copyright (C) 2006-2007 Kevin Ottens + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#ifndef SOLID_POWERMANAGER_P_H +#define SOLID_POWERMANAGER_P_H + +#include "managerbase_p.h" + +#include "powermanager.h" + +namespace Solid +{ +namespace Control +{ + class PowerManagerPrivate : public PowerManager::Notifier, public ManagerBasePrivate + { + Q_OBJECT + public: + PowerManagerPrivate(); + ~PowerManagerPrivate(); + }; +} +} + +#endif diff --git a/solid/control/singletondefs.h b/solid/control/singletondefs.h new file mode 100644 index 000000000..1b6244431 --- /dev/null +++ b/solid/control/singletondefs.h @@ -0,0 +1,56 @@ +/* This file is part of the KDE project + Copyright (C) 2006-2007 Kevin Ottens + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#ifndef SOLID_CONTROL_SINGLETONDEFS_H +#define SOLID_CONTROL_SINGLETONDEFS_H + +#include + +class QObject; + +namespace Solid +{ +namespace Control +{ + /** + * @internal + */ + template + class SingletonHelper { public: T instance; }; + +#define SOLID_SINGLETON(Type) \ +public: \ + static Type &self(); \ + static Type &selfForceBackend(QObject *backend); \ +private: \ + friend class Solid::Control::SingletonHelper< Type >; + +#define SOLID_SINGLETON_IMPLEMENTATION(Type, Name) \ + K_GLOBAL_STATIC(Solid::Control::SingletonHelper< Type >, global##Name) \ + \ + Type &Type::self() \ + { \ + Solid::Control::SingletonHelper< Type > *singleton = global##Name; \ + \ + return singleton->instance; \ + } +} +} + +#endif diff --git a/solid/control/solid_control_export.h b/solid/control/solid_control_export.h new file mode 100644 index 000000000..1e0afbb10 --- /dev/null +++ b/solid/control/solid_control_export.h @@ -0,0 +1,56 @@ +/* This file is part of the KDE project + Copyright (C) 2006 David Faure + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This 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 SOLID_CONTROL_EXPORT_H +#define SOLID_CONTROL_EXPORT_H + +/* needed for KDE_EXPORT and KDE_IMPORT macros */ +#include + +/* We use _WIN32/_WIN64 instead of Q_OS_WIN so that this header can be used from C files too */ +#if defined _WIN32 || defined _WIN64 + +#ifndef SOLIDCONTROL_EXPORT +# if defined(MAKE_SOLIDCONTROL_LIB) + /* We are building this library */ +# define SOLIDCONTROL_EXPORT KDE_EXPORT +# else + /* We are using this library */ +# define SOLIDCONTROL_EXPORT KDE_IMPORT +# endif +#endif + +#ifndef SOLIDCONTROLIFACES_EXPORT +# if defined(MAKE_SOLIDCONTROLIFACES_LIB) + /* We are building this library */ +# define SOLIDCONTROLIFACES_EXPORT KDE_EXPORT +# else + /* We are using this library */ +# define SOLIDCONTROLIFACES_EXPORT KDE_IMPORT +# endif +#endif + +#else /* UNIX */ + +#define SOLIDCONTROL_EXPORT KDE_EXPORT +#define SOLIDCONTROLIFACES_EXPORT KDE_EXPORT + +#endif + +#endif diff --git a/solid/control/solidbluetoothmanager.desktop b/solid/control/solidbluetoothmanager.desktop new file mode 100644 index 000000000..1d25505a3 --- /dev/null +++ b/solid/control/solidbluetoothmanager.desktop @@ -0,0 +1,68 @@ +[Desktop Entry] +Type=ServiceType +X-KDE-ServiceType=SolidBluetoothManager + +Comment=Bluetooth Management Backend +Comment[af]=Bluetooth-beheer agtergrondprogram +Comment[be]=Кіраванне Bluetooth +Comment[be@latin]=Кіраванне Bluetooth +Comment[bg]=Заден слой за управление на Bluetooth +Comment[ca]=Dorsal de gestió de bluetooth +Comment[da]=Håndteringsmotor for Bluetooth +Comment[de]=Backend zur Bluetooth-Verwaltung +Comment[el]=Σύστημα διαχείρισης Bluetooth +Comment[eo]=Bluetooth-administra plenumilo +Comment[es]=Motor de gestión de Bluetooth +Comment[et]=Bluetoothi haldamise taustaprogramm +Comment[eu]=Bluetooth kudeatzeko interfazea +Comment[fa]=پایانۀ پشتیبانی مدیریت بلوتوث +Comment[fi]=Bluetooth-hallinnan taustaosa +Comment[fr]=Interface de gestion Bluetooth +Comment[fy]=Bluetooth behear backend +Comment[ga]=Inneall Bainisteoireachta Bluetooth +Comment[gl]=Infraestrutura de xestión de Bluetooth +Comment[gu]=બ્લ્યુટૂથ વ્યવસ્થાપક બેકએન્ડ +Comment[he]=ממשק ניהול Bluetooth +Comment[hi]=ब्लूटूथ प्रबंधन बैकएण्ड +Comment[hu]=Bluetooth-kezelő modul +Comment[is]=Blátannarstýringarkerfi +Comment[it]=Backend per la gestione di Blutooth +Comment[ja]=Bluetooth 管理のバックエンド +Comment[kk]=Bluetooth басқару тетігі +Comment[km]=ការ​គ្រប់គ្រង​ប៊្លូធូស​​កម្មវិធី​ខាង​ក្រោយ +Comment[kn]=ಬ್ಲೂಟೂತ್ ಹಿನ್ನೆಲೆ (ಬಾಕೆ ಎಂಡ್) ವ್ಯವಸ್ಥಾಪನೆ +Comment[ko]=블루투스 관리 백엔드 +Comment[lt]=Bluetooth tvarkymo programinė sąsaja +Comment[lv]=Bluetooth pārvaldības aizmugure +Comment[ml]=ബ്ലൂടൂത് മാനേജ്മെന്റ് ബാക്കെന്‍ഡ് +Comment[mr]=ब्लूटूथ व्यवस्थापन बैकएण्ड +Comment[nb]=Bakgrunnsmotor for Bluetooth-styring +Comment[nds]=Hülprogramm för den Bluetooth-Pleger +Comment[ne]=ब्लुटुथ व्यवस्थापन ब्याकइन्ड +Comment[nl]=Bluetooth-beheer backend +Comment[nn]=Motor for Bluetooth-handtering +Comment[pa]=ਬਲਿਊਟੁੱਥ ਮੈਨਿਜਮੈਂਟ ਬੈਕਐਂਡ +Comment[pl]=Usługa zarządzania połączeniami Bluetooth +Comment[pt]=Infra-Estrutura de Gestão do Bluetooth +Comment[pt_BR]=Infra-estrutura do Gerenciamento de Bluetooth +Comment[ro]=Suport pentru administrare bluetooth +Comment[ru]=Модуль управления протоколом Bluetooth +Comment[se]=Bluetooth-gieđahallanmohtor +Comment[sl]=Hrbtenica za upravljanje z Bluetooth +Comment[sr]=Позадина за управљање блутутом +Comment[sr@latin]=Pozadina za upravljanje Bluetoothom +Comment[sv]=Blåtandshanteringsgränssnitt +Comment[te]=బ్లూటూత్ నిర్వహణా బ్యాక్ఎండ్ +Comment[tg]=Пуштибонии идоракунии Bluetooth +Comment[th]=โปรแกรมเบื้องหลังการจัดการบลูทูธ +Comment[tr]=Bluetooth Yönetimi Arka Ucu +Comment[uk]=Програма керування Bluetooth +Comment[vi]=Hậu phương quản lý kỹ thuật Bluetooth +Comment[wa]=Bouye di fond di manaedjmint Bluetooth +Comment[x-test]=xxBluetooth Management Backendxx +Comment[zh_CN]=蓝牙管理后端 +Comment[zh_TW]=藍芽管理後端介面 + +[PropertyDef::X-KDE-SolidBackendInfo-Version] +Type=QString + diff --git a/solid/control/soliddefs_p.h b/solid/control/soliddefs_p.h new file mode 100644 index 000000000..561b8a969 --- /dev/null +++ b/solid/control/soliddefs_p.h @@ -0,0 +1,49 @@ +/* This file is part of the KDE project + Copyright (C) 2006-2007 Kevin Ottens + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#ifndef SOLID_SOLIDDEFS_P_H +#define SOLID_SOLIDDEFS_P_H + +#include + + + +#define return_SOLID_CALL(Type, Object, Default, Method) \ + Type t = qobject_cast(Object); \ + if (t!=0) \ + { \ + return t->Method; \ + } \ + else \ + { \ + return Default; \ + } + + + +#define SOLID_CALL(Type, Object, Method) \ + Type t = qobject_cast(Object); \ + if (t!=0) \ + { \ + t->Method; \ + } + + + +#endif diff --git a/solid/control/solidnetworkmanager.desktop b/solid/control/solidnetworkmanager.desktop new file mode 100644 index 000000000..fc323294d --- /dev/null +++ b/solid/control/solidnetworkmanager.desktop @@ -0,0 +1,66 @@ +[Desktop Entry] +Type=ServiceType +X-KDE-ServiceType=SolidNetworkManager + +Comment=Network Management Backend +Comment[af]=Netwerk-beheer agtergrondprogram +Comment[be]=Кіраванне сеткай +Comment[be@latin]=Кіраванне сеткай +Comment[bg]=Заден слой за управление на мрежа +Comment[ca]=Dorsal de gestió de xarxa +Comment[da]=Håndteringsmotor for netværk +Comment[de]=Backend zur Netzwerkverwaltung +Comment[el]=Σύστημα διαχείρισης δικτύου +Comment[eo]=Retadministra plenumilo +Comment[es]=Motor de gestión de redes +Comment[et]=Võrgu haldamise taustaprogramm +Comment[eu]=Sarea kudeatzeko interfazea +Comment[fa]=پایانۀ پشتیبانی مدیریت شبکه +Comment[fi]=Verkon hallinnan taustaosa +Comment[fr]=Interface de gestion du réseau +Comment[fy]=Network behear backend +Comment[ga]=Inneall Bainisteoireachta Líonra +Comment[gl]=Infraestrutura de xestión da rede +Comment[gu]=નેટવર્ક વ્યવસ્થાપક બેકએન્ડ +Comment[he]=ממשק ניהול רשת +Comment[hi]=नेटवर्क प्रबंधन बैकएण्ड +Comment[hu]=Hálózatkezelő modul +Comment[is]=Netstýringakerfi +Comment[it]=Backend per la gestione di rete +Comment[ja]=ネットワーク管理のバックエンド +Comment[kk]=Желіні басқару тетігі +Comment[km]=ការ​គ្រប់គ្រង​បណ្តាញ​កម្មវិធី​ខាងក្រោយ +Comment[kn]=ಜಾಲ ವ್ಯವಸ್ಥಾಪನೆ ಹಿನ್ನೆಲೆ (ಬಾಕೆ ಎಂಡ್) +Comment[ko]=네트워크 관리 백엔드 +Comment[lv]=Tīkla pārvaldes aizmugure +Comment[ml]=നെറ്റ്‌വര്‍ക്ക് മാനേജ്മെന്റ് ബാക്കെന്‍ഡ് +Comment[mr]=संजाळ व्यवस्थापन बैकएण्ड +Comment[nb]=Bakgrunnsmotor for nettverksstyring +Comment[nds]=Hülpprogramm för den Nettwark-Pleger +Comment[ne]=सञ्जाल व्यवस्थापन ब्याकइन्ड +Comment[nl]=Netwerkbeheer backend +Comment[nn]=Motor for nettverkshandtering +Comment[pa]=ਨੈੱਟਵਰਕ ਮੈਨਿਜਮੈਂਟ ਬੈਕਐਂਡ +Comment[pl]=Usługa zarządzania siecią +Comment[pt]=Infra-Estrutura de Gestão da Rede +Comment[pt_BR]=Infra-estrutura do Gerenciamento de Rede +Comment[ro]=Suport pentru gestiune rețea +Comment[ru]=Модуль управления сетью +Comment[se]=Fierpmádatgieđahallanmohtor +Comment[sl]=Hrbtenica za upravljanje z omrežji +Comment[sr]=Позадина за управљање мрежом +Comment[sr@latin]=Pozadina za upravljanje mrežom +Comment[sv]=Nätverkshanteringsgränssnitt +Comment[te]=నెట్వర్‍క్ నిర్వహణా బ్యాక్ఎండ్ +Comment[tg]=Пуштибонии идоракунии шабака +Comment[th]=โปรแกรมเบื้องหลังการจัดการเครือข่าย +Comment[tr]=Ağ Yönetimi Arka Ucu +Comment[uk]=Програма керування мережею +Comment[vi]=Hậu phương quản lý mạng +Comment[x-test]=xxNetwork Management Backendxx +Comment[zh_CN]=网络管理后端 +Comment[zh_TW]=網路管理後端介面 + +[PropertyDef::X-KDE-SolidBackendInfo-Version] +Type=QString + diff --git a/solid/control/solidpowermanager.desktop b/solid/control/solidpowermanager.desktop new file mode 100644 index 000000000..4805c101c --- /dev/null +++ b/solid/control/solidpowermanager.desktop @@ -0,0 +1,67 @@ +[Desktop Entry] +Type=ServiceType +X-KDE-ServiceType=SolidPowerManager + +Comment=Power Management Backend +Comment[af]=Krag-beheer agtergrondprogram +Comment[be]=Кіраванне сілкаваннем +Comment[be@latin]=Кіраванне сілкаваннем +Comment[bg]=Заден слой за управление на захранване +Comment[ca]=Dorsal de gestió d'energia +Comment[da]=Motor for strømstyring +Comment[de]=Backend zur Energieverwaltung +Comment[el]=Σύστημα διαχείρισης ενέργειας +Comment[eo]=Energiadministrada interno +Comment[es]=Motor de la gestión de energía +Comment[et]=Voolutarbe haldamise taustaprogramm +Comment[eu]=Energia kudeatzeko interfazea +Comment[fa]=پایانۀ پشتیبانی مدیریت توان +Comment[fi]=Tulostuksenhallinnan taustaosa +Comment[fr]=Interface de gestion de l'énergie +Comment[fy]=Enerzjybehear backend +Comment[ga]=Inneall Bainisteoireachta Cumhachta +Comment[gl]=Infraestrutura de xestión da enerxía +Comment[gu]=પાવર વ્યવસ્થાપક બેકએન્ડ +Comment[he]=ממשק ניהול צריכת חשמל +Comment[hi]=पॉवर प्रबंधन बैकएण्ड +Comment[hu]=Energiakezelő modul +Comment[is]=Orkustýringarkerfi +Comment[it]=Backend per la gestione dell'energia +Comment[ja]=電源管理のバックエンド +Comment[kk]=Қуаттандыруды басқару тетігі +Comment[km]=ការ​គ្រប់គ្រង​ថាមពល​កម្មវិធី​ខាង​ក្រោយ +Comment[kn]=ವಿದ್ಯುಚ್ಛಕ್ತಿ ವ್ಯವಸ್ಥಾಪನೆ ಹಿನ್ನೆಲೆ (ಬಾಕ್ ಎಂಡ್) +Comment[ko]=전력 관리 백엔드 +Comment[lv]=Energokontroles aizmugure +Comment[ml]=പവര്‍ മാനേജ്മെന്റ് ബാക്കെന്‍ഡ് +Comment[mr]=पॉवर व्यवस्थापन बैकएण्ड +Comment[nb]=Bakgrunnsmotor for strømstyring +Comment[nds]=Hülpprogramm för de Stroomkuntrull +Comment[ne]=शक्ति व्यवस्थापन ब्याकइन्ड +Comment[nl]=Energiebeheer backend +Comment[nn]=Motor for straumstyring +Comment[pa]=ਪਾਵਰ ਮੈਨਿਜਮੈਂਟ ਬੈਕਐਂਡ +Comment[pl]=Usługa zarządzania energią +Comment[pt]=Infra-Estrutura de Gestão da Energia +Comment[pt_BR]=Infra-estrutura do Gerenciamento de Energia +Comment[ro]=Suport pentru administrare de energie +Comment[ru]=Модуль управления питанием +Comment[se]=El-rávdnjegieđahallanmohtor +Comment[sl]=Hrbtenica za upravljanje z energijo +Comment[sr]=Позадина за управљање енергијом +Comment[sr@latin]=Pozadina za upravljanje energijom +Comment[sv]=Gränssnitt för strömsparhantering +Comment[te]=పవర్ నిర్వహణా బ్యాక్ఎండ్ +Comment[tg]=Пуштибонии идоракунии барқи батарея +Comment[th]=โปรแกรมเบื้องหลังการจัดการพลังงาน +Comment[tr]=Güç Yönetimi Arka Ucu +Comment[uk]=Програма керування живленням +Comment[vi]=Hậu phương quản lý nguồn điện +Comment[wa]=Bouye di fond di manaedjmint di l' enerdjeye +Comment[x-test]=xxPower Management Backendxx +Comment[zh_CN]=电源管理后端 +Comment[zh_TW]=電源管理後端介面 + +[PropertyDef::X-KDE-SolidBackendInfo-Version] +Type=QString + diff --git a/solid/control/tests/CMakeLists.txt b/solid/control/tests/CMakeLists.txt new file mode 100644 index 000000000..b2da098c6 --- /dev/null +++ b/solid/control/tests/CMakeLists.txt @@ -0,0 +1,30 @@ +set( EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR} ) + + +########### solidnettest ############### + +#set(solidnettest_SRCS +# solidnettest.cpp ) + + +#kde4_add_unit_test(solidnettest ${solidnettest_SRCS}) +#add_definitions(-DFAKE_NETWORKING_XML="\\"${CMAKE_CURRENT_SOURCE_DIR}/../backends/fakenet/fakenetworking.xml\\"") + +#include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/../backends/fakenet ) + +#target_link_libraries(solidnettest ${KDE4_KDECORE_LIBS} ${QT_QTTEST_LIBRARY} solidcontrol solidcontrolifaces solid_fakenet_static) + +########### solidbluetoothtest ############### + +#set(solidbluetoothtest_SRCS +# solidbluetoothtest.cpp ) + + +#kde4_add_unit_test(solidbluetoothtest ${solidbluetoothtest_SRCS}) +#add_definitions(-DFAKE_BLUETOOTH_XML="\\"${CMAKE_CURRENT_SOURCE_DIR}/../backends/fakebluetooth/fakebluetooth.xml\\"") + +#include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/../backends/fakebluetooth ) + +#target_link_libraries(solidbluetoothtest ${KDE4_KDECORE_LIBS} ${QT_QTTEST_LIBRARY} solidcontrol solidcontrolifaces solid_fakebluetooth_static) + +########### install files ############### diff --git a/solid/control/tests/solidbluetoothtest.cpp b/solid/control/tests/solidbluetoothtest.cpp new file mode 100644 index 000000000..85bf95531 --- /dev/null +++ b/solid/control/tests/solidbluetoothtest.cpp @@ -0,0 +1,80 @@ +/* This file is part of the KDE project + Copyright (C) 2005 Kevin Ottens + Copyright (C) 2007 Daniel Gollub + + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#include "solidbluetoothtest.h" + +#include + +#include +#include +#include "solid/control/managerbase_p.h" +#include + +#include + +#ifndef FAKE_BLUETOOTH_XML +#error "FAKE_BLUETOOTH_XML not set. An XML file describing a bluetooth context is required for this test" +#endif + +QTEST_KDEMAIN_CORE(SolidBluetoothTest) + +void SolidBluetoothTest::initTestCase() +{ + fakeManager = new FakeBluetoothManager(0, QStringList(), FAKE_BLUETOOTH_XML); + Solid::Control::ManagerBasePrivate::_k_forcePreloadedBackend("Solid::Control::Ifaces::BluetoothManager", fakeManager); +} + +void SolidBluetoothTest::testBluetoothInterfaces() +{ + Solid::Control::BluetoothManager &manager = Solid::Control::BluetoothManager::self(); + + Solid::Control::BluetoothInterfaceList interfaces = manager.bluetoothInterfaces(); + + // Verify that the framework reported correctly the interfaces available + // in the backend. + QSet expected_ubis, received_ubis; + + expected_ubis = QSet::fromList(fakeManager->bluetoothInterfaces()); + + foreach (Solid::Control::BluetoothInterface iface , interfaces) { + received_ubis << iface.ubi(); + } + + QCOMPARE(expected_ubis, received_ubis); +} + +void SolidBluetoothTest::testManagerBasicFeatures() +{ + //Solid::Control::BluetoothManager &manager = Solid::Control::BluetoothManager::self(); + +} + +void SolidBluetoothTest::testInterfaceBasicFeatures() +{ + //Solid::Control::BluetoothManager &manager = Solid::Control::BluetoothManager::self(); + + // Retrieve a valid BluetoothInterface object + Solid::Control::BluetoothInterface valid_iface("/org/kde/solid/fakebluetooth/hci0"); + +} + +#include "solidbluetoothtest.moc" + diff --git a/solid/control/tests/solidbluetoothtest.h b/solid/control/tests/solidbluetoothtest.h new file mode 100644 index 000000000..d2f94b999 --- /dev/null +++ b/solid/control/tests/solidbluetoothtest.h @@ -0,0 +1,42 @@ +/* This file is part of the KDE project + Copyright (C) 2005 Kevin Ottens + Copyright (C) 2007 Daniel Gollub + + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#ifndef SOLIDBLUETOOTHTEST_H +#define SOLIDBLUETOOTHTEST_H + +#include + +class FakeBluetoothManager; + +class SolidBluetoothTest : public QObject +{ + Q_OBJECT +private slots: + void initTestCase(); + void testBluetoothInterfaces(); + void testManagerBasicFeatures(); + void testInterfaceBasicFeatures(); + +private: + FakeBluetoothManager *fakeManager; +}; + +#endif diff --git a/solid/control/tests/solidnettest.cpp b/solid/control/tests/solidnettest.cpp new file mode 100644 index 000000000..0debc04eb --- /dev/null +++ b/solid/control/tests/solidnettest.cpp @@ -0,0 +1,157 @@ +/* This file is part of the KDE project + Copyright (C) 2005 Kevin Ottens + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#include "solidnettest.h" + +#include + +#include +#include +#include +#include + +#include + +#ifndef FAKE_NETWORKING_XML + #error "FAKE_NETWORKING_XML not set. An XML file describing a networking context is required for this test" +#endif + +QTEST_KDEMAIN_CORE(SolidNetTest) + +void SolidNetTest::initTestCase() +{ + fakeManager = new FakeNetworkManager(0, QStringList(), FAKE_NETWORKING_XML); + Solid::Control::ManagerBasePrivate::_k_forcePreloadedBackend("Solid::Control::Ifaces::NetworkManager", fakeManager); +} + +void SolidNetTest::testNetworkInterfaces() +{ + Solid::Control::NetworkInterfaceList interfaces = Solid::Control::NetworkManager::networkInterfaces(); + + // Verify that the framework reported correctly the interfaces available + // in the backend. + QSet expected_unis, received_unis; + + expected_unis = QSet::fromList(fakeManager->networkInterfaces()); + + foreach (Solid::Control::NetworkInterface iface , interfaces) + { + received_unis << iface.uni(); + } + + QCOMPARE(expected_unis, received_unis); +} + +void SolidNetTest::testFindNetworkInterface() +{ + QCOMPARE(Solid::Control::NetworkManager::findNetworkInterface("/org/kde/solid/fakenet/eth0").isValid(), true); + QCOMPARE(Solid::Control::NetworkManager::findNetworkInterface("/org/kde/solid/fakenet/eth1").isValid(), true); + + // Note the extra space + QCOMPARE(Solid::Control::NetworkManager::findNetworkInterface("/org/kde/solid/fakenet/eth0 ").isValid(), false); + QCOMPARE(Solid::Control::NetworkManager::findNetworkInterface("#'({(�").isValid(), false); + QCOMPARE(Solid::Control::NetworkManager::findNetworkInterface(QString()).isValid(), false); +} + +void SolidNetTest::testManagerBasicFeatures() +{ + QCOMPARE(Solid::Control::NetworkManager::isNetworkingEnabled(), true); + QCOMPARE(Solid::Control::NetworkManager::isWirelessEnabled(), true); + + Solid::Control::NetworkManager::setNetworkingEnabled(false); + + QCOMPARE(Solid::Control::NetworkManager::isNetworkingEnabled(), false); + QCOMPARE(Solid::Control::NetworkManager::isWirelessEnabled(), false); + + Solid::Control::NetworkManager::setNetworkingEnabled(true); + + QCOMPARE(Solid::Control::NetworkManager::isNetworkingEnabled(), true); + QCOMPARE(Solid::Control::NetworkManager::isWirelessEnabled(), true); + + Solid::Control::NetworkManager::setWirelessEnabled(false); + + QCOMPARE(Solid::Control::NetworkManager::isNetworkingEnabled(), true); + QCOMPARE(Solid::Control::NetworkManager::isWirelessEnabled(), false); + + Solid::Control::NetworkManager::setNetworkingEnabled(false); + + QCOMPARE(Solid::Control::NetworkManager::isNetworkingEnabled(), false); + QCOMPARE(Solid::Control::NetworkManager::isWirelessEnabled(), false); + + Solid::Control::NetworkManager::setNetworkingEnabled(true); + + QCOMPARE(Solid::Control::NetworkManager::isNetworkingEnabled(), true); + QCOMPARE(Solid::Control::NetworkManager::isWirelessEnabled(), false); + + Solid::Control::NetworkManager::setWirelessEnabled(true); + + QCOMPARE(Solid::Control::NetworkManager::isNetworkingEnabled(), true); + QCOMPARE(Solid::Control::NetworkManager::isWirelessEnabled(), true); +} + +void SolidNetTest::testInterfaceBasicFeatures() +{ + // Retrieve a valid NetworkInterface object + Solid::Control::NetworkInterface valid_iface("/org/kde/solid/fakenet/eth0"); + + QCOMPARE(valid_iface.isValid(), true); + + + // A few attempts at creating invalid Device objects + Solid::Control::NetworkInterface invalid_iface("uhoh? doesn't exist, I guess"); + QCOMPARE(invalid_iface.isValid(), false); + invalid_iface = Solid::Control::NetworkManager::findNetworkInterface(QString()); + QCOMPARE(invalid_iface.isValid(), false); + invalid_iface = Solid::Control::NetworkInterface(); + QCOMPARE(invalid_iface.isValid(), false); + + + + QCOMPARE(valid_iface.uni(), QString("/org/kde/solid/fakenet/eth0")); + QCOMPARE(invalid_iface.uni(), QString()); + + + QCOMPARE(valid_iface.isActive(), true); + QCOMPARE(valid_iface.type(), Solid::Control::NetworkInterface::Ieee80211); + QCOMPARE(valid_iface.connectionState(), Solid::Control::NetworkInterface::NeedUserKey); + QCOMPARE(valid_iface.signalStrength(), 90); + QCOMPARE(valid_iface.designSpeed(), 83886080); + QCOMPARE(valid_iface.isLinkUp(), true); + QCOMPARE(valid_iface.capabilities(), Solid::Control::NetworkInterface::IsManageable + |Solid::Control::NetworkInterface::SupportsCarrierDetect + |Solid::Control::NetworkInterface::SupportsWirelessScan); + + QVERIFY(valid_iface.findNetwork("/org/kde/solid/fakenet/eth0/net1")!=0); + QCOMPARE(valid_iface.findNetwork("/org/kde/solid/fakenet/eth0/net1")->isValid(), true); + + QVERIFY(valid_iface.findNetwork("emldzn")!=0); + QCOMPARE(valid_iface.findNetwork("emldzn")->isValid(), false); + + QVERIFY(valid_iface.findNetwork("/org/kde/solid/fakenet/eth1/net0")!=0); + QCOMPARE(valid_iface.findNetwork("/org/kde/solid/fakenet/eth1/net0")->isValid(), false); + + QVERIFY(valid_iface.findNetwork("/org/kde/solid/fakenet/eth0/net0 ")!=0); + QCOMPARE(valid_iface.findNetwork("/org/kde/solid/fakenet/eth0/net0")->isValid(), true); + + QCOMPARE(valid_iface.findNetwork("/org/kde/solid/fakenet/eth0/net0")->addressEntries().size(), 1); + QCOMPARE(valid_iface.networks().size(), 4); +} + +#include "solidnettest.moc" + diff --git a/solid/control/tests/solidnettest.h b/solid/control/tests/solidnettest.h new file mode 100644 index 000000000..d6e099f59 --- /dev/null +++ b/solid/control/tests/solidnettest.h @@ -0,0 +1,41 @@ +/* This file is part of the KDE project + Copyright (C) 2005 Kevin Ottens + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#ifndef SOLIDNETTEST_H +#define SOLIDNETTEST_H + +#include + +class FakeNetworkManager; + +class SolidNetTest : public QObject +{ + Q_OBJECT +private slots: + void initTestCase(); + void testNetworkInterfaces(); + void testFindNetworkInterface(); + void testManagerBasicFeatures(); + void testInterfaceBasicFeatures(); + +private: + FakeNetworkManager *fakeManager; +}; + +#endif diff --git a/solid/control/wirednetworkinterface.cpp b/solid/control/wirednetworkinterface.cpp new file mode 100644 index 000000000..cde19447d --- /dev/null +++ b/solid/control/wirednetworkinterface.cpp @@ -0,0 +1,96 @@ +/* This file is part of the KDE project + Copyright (C) 2006 Will Stephenson + Copyright (C) 2007 Kevin Ottens + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#include "wirednetworkinterface.h" +#include "wirednetworkinterface_p.h" + +#include "soliddefs_p.h" +#include "ifaces/wirednetworkinterface.h" + +Solid::Control::WiredNetworkInterface::WiredNetworkInterface(QObject *backendObject) + : NetworkInterface(*new WiredNetworkInterfacePrivate(this), backendObject) +{ + Q_D(WiredNetworkInterface); + d->setBackendObject(backendObject); +} + +Solid::Control::WiredNetworkInterface::WiredNetworkInterface(const WiredNetworkInterface &networkinterface) + : NetworkInterface(*new WiredNetworkInterfacePrivate(this), networkinterface) +{ + Q_D(WiredNetworkInterface); + d->setBackendObject(networkinterface.d_ptr->backendObject()); +} + +Solid::Control::WiredNetworkInterface::WiredNetworkInterface(WiredNetworkInterfacePrivate &dd, QObject *backendObject) + : NetworkInterface(dd, backendObject) +{ +} + +Solid::Control::WiredNetworkInterface::WiredNetworkInterface(WiredNetworkInterfacePrivate &dd, const WiredNetworkInterface &network) + : NetworkInterface(dd, network.d_ptr->backendObject()) +{ +} + +Solid::Control::WiredNetworkInterface::~WiredNetworkInterface() +{ + +} + +Solid::Control::NetworkInterface::Type Solid::Control::WiredNetworkInterface::type() const +{ + return Ieee8023; +} + +QString Solid::Control::WiredNetworkInterface::hardwareAddress() const +{ + Q_D(const WiredNetworkInterface); + return_SOLID_CALL(Ifaces::WiredNetworkInterface *, d->backendObject(), QString(), hardwareAddress()); +} + +int Solid::Control::WiredNetworkInterface::bitRate() const +{ + Q_D(const WiredNetworkInterface); + return_SOLID_CALL(Ifaces::WiredNetworkInterface *, d->backendObject(), 0, bitRate()); +} + +bool Solid::Control::WiredNetworkInterface::carrier() const +{ + Q_D(const WiredNetworkInterface); + return_SOLID_CALL(Ifaces::WiredNetworkInterface *, d->backendObject(), false, carrier()); +} + +void Solid::Control::WiredNetworkInterfacePrivate::setBackendObject(QObject *object) +{ + NetworkInterfacePrivate::setBackendObject(object); + + if (object) { + QObject::connect(object, SIGNAL(bitRateChanged(int)), + parent(), SIGNAL(bitRateChanged(int))); + QObject::connect(object, SIGNAL(carrierChanged(bool)), + parent(), SIGNAL(carrierChanged(bool))); + } +} + +void Solid::Control::WiredNetworkInterface::_k_destroyed(QObject *object) +{ + Q_UNUSED(object); + // nothing to do yet +} +#include "wirednetworkinterface.moc" diff --git a/solid/control/wirednetworkinterface.h b/solid/control/wirednetworkinterface.h new file mode 100644 index 000000000..5a6fb72ff --- /dev/null +++ b/solid/control/wirednetworkinterface.h @@ -0,0 +1,122 @@ +/* This file is part of the KDE project + Copyright (C) 2006 Will Stephenson + Copyright (C) 2007 Kevin Ottens + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#ifndef SOLID_CONTROL_WIREDNETWORKINTERFACE_H +#define SOLID_CONTROL_WIREDNETWORKINTERFACE_H + +#include "solid_control_export.h" + +#include "networkinterface.h" + +namespace Solid +{ +namespace Control +{ + class WiredNetworkInterfacePrivate; + + /** + * This interface represents a wired Ethernet network interface + */ + class SOLIDCONTROL_EXPORT WiredNetworkInterface : public NetworkInterface + { + Q_OBJECT + Q_DECLARE_PRIVATE(WiredNetworkInterface) + + public: + /** + * Creates a new WiredNetworkInterface object. + * + * @param backendObject the network object provided by the backend + */ + WiredNetworkInterface(QObject *backendObject = 0); + + /** + * Constructs a copy of a network. + * + * @param network the network to copy + */ + WiredNetworkInterface(const WiredNetworkInterface &network); + + /** + * Destroys a WiredNetworkInterface object. + */ + virtual ~WiredNetworkInterface(); + + /** + * The NetworkInterface type. + * + * @return the NetworkInterface::Type. This always returns NetworkInterface::Ieee8023 + */ + virtual NetworkInterface::Type type() const; + + /** + * The hardware address assigned to the network interface + */ + QString hardwareAddress() const; + + /** + * Retrieves the effective bit rate currently attainable by this device. + * + * @return the bitrate in bit/s + */ + int bitRate() const; + + /** + * Indicates if the network interfaces sees a carrier. + * + * @return true if there's a carrier, false otherwise + */ + bool carrier() const; + + Q_SIGNALS: + /** + * This signal is emitted when the bitrate of this network has changed. + * + * @param bitrate the new bitrate value for this network + */ + void bitRateChanged(int bitRate); + + /** + * This signal indicates if the physical carrier changed state (eg if the network cable was + * plugged or unplugged) + */ + void carrierChanged(bool plugged); + protected: + /** + * @internal + */ + WiredNetworkInterface(WiredNetworkInterfacePrivate &dd, QObject *backendObject); + + /** + * @internal + */ + WiredNetworkInterface(WiredNetworkInterfacePrivate &dd, const WiredNetworkInterface &network); + + private Q_SLOTS: + void _k_destroyed(QObject *object); + private: + friend class NetworkInterface; + friend class NetworkInterfacePrivate; + }; +} //Control +} //Solid + +#endif //SOLID_CONTROL_WIREDNETWORKINTERFACE_H + diff --git a/solid/control/wirednetworkinterface_p.h b/solid/control/wirednetworkinterface_p.h new file mode 100644 index 000000000..978e7db24 --- /dev/null +++ b/solid/control/wirednetworkinterface_p.h @@ -0,0 +1,41 @@ +/* This file is part of the KDE project + Copyright (C) 2006 Will Stephenson + Copyright (C) 2007 Kevin Ottens + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#ifndef SOLID_NETWORK_P_H +#define SOLID_NETWORK_P_H + +#include "networkinterface_p.h" + +namespace Solid +{ +namespace Control +{ + class WiredNetworkInterfacePrivate : public NetworkInterfacePrivate + { + public: + explicit WiredNetworkInterfacePrivate(QObject *parent) + : NetworkInterfacePrivate(parent) { } + + void setBackendObject(QObject *object); + }; +} +} + +#endif diff --git a/solid/control/wirelessaccesspoint.cpp b/solid/control/wirelessaccesspoint.cpp new file mode 100644 index 000000000..84ef00db6 --- /dev/null +++ b/solid/control/wirelessaccesspoint.cpp @@ -0,0 +1,165 @@ +/* +Copyright 2008 Will Stephenson + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) version 3, or any +later version accepted by the membership of KDE e.V. (or its +successor approved by the membership of KDE e.V.), which shall +act as a proxy defined in Section 6 of version 3 of the license. + +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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library. If not, see . +*/ + +#include "wirelessaccesspoint.h" +#include "frontendobject_p.h" +#include "soliddefs_p.h" +#include "ifaces/wirelessaccesspoint.h" + +namespace Solid +{ +namespace Control +{ + class AccessPointPrivate : public FrontendObjectPrivate + { + public: + AccessPointPrivate(QObject *parent) + : FrontendObjectPrivate(parent) { } + + void setBackendObject(QObject *object); + }; +} +} + +Solid::Control::AccessPoint::AccessPoint(QObject *backendObject) + : QObject(), d_ptr(new AccessPointPrivate(this)) +{ + Q_D(AccessPoint); + d->setBackendObject(backendObject); +} + +Solid::Control::AccessPoint::AccessPoint(const AccessPoint &network) + : QObject(), d_ptr(new AccessPointPrivate(this)) +{ + Q_D(AccessPoint); + d->setBackendObject(network.d_ptr->backendObject()); +} + +Solid::Control::AccessPoint::AccessPoint(AccessPointPrivate &dd, QObject *backendObject) + : QObject(), d_ptr(&dd) +{ + Q_D(AccessPoint); + d->setBackendObject(backendObject); +} + +Solid::Control::AccessPoint::AccessPoint(AccessPointPrivate &dd, const AccessPoint &ap) + : d_ptr(&dd) +{ + Q_D(AccessPoint); + d->setBackendObject(ap.d_ptr->backendObject()); +} + +Solid::Control::AccessPoint::~AccessPoint() +{ + delete d_ptr; +} + +QString Solid::Control::AccessPoint::uni() const +{ + Q_D(const AccessPoint); + return_SOLID_CALL(Ifaces::AccessPoint *, d->backendObject(), QString(), uni()); +} + +Solid::Control::AccessPoint::Capabilities Solid::Control::AccessPoint::capabilities() const +{ + Q_D(const AccessPoint); + return_SOLID_CALL(Ifaces::AccessPoint *, d->backendObject(), 0, capabilities()); + +} + +Solid::Control::AccessPoint::WpaFlags Solid::Control::AccessPoint::wpaFlags() const +{ + Q_D(const AccessPoint); + return_SOLID_CALL(Ifaces::AccessPoint *, d->backendObject(), 0, wpaFlags()); + +} + +Solid::Control::AccessPoint::WpaFlags Solid::Control::AccessPoint::rsnFlags() const +{ + Q_D(const AccessPoint); + return_SOLID_CALL(Ifaces::AccessPoint *, d->backendObject(), 0, rsnFlags()); + +} + +QString Solid::Control::AccessPoint::ssid() const +{ + Q_D(const AccessPoint); + return_SOLID_CALL(Ifaces::AccessPoint *, d->backendObject(), QString(), ssid()); +} + +uint Solid::Control::AccessPoint::frequency() const +{ + Q_D(const AccessPoint); + return_SOLID_CALL(Ifaces::AccessPoint *, d->backendObject(), 0, frequency()); + +} + +QString Solid::Control::AccessPoint::hardwareAddress() const +{ + Q_D(const AccessPoint); + return_SOLID_CALL(Ifaces::AccessPoint *, d->backendObject(), QString(), hardwareAddress()); + +} + +uint Solid::Control::AccessPoint::maxBitRate() const +{ + Q_D(const AccessPoint); + return_SOLID_CALL(Ifaces::AccessPoint *, d->backendObject(), 0, maxBitRate()); +} + +Solid::Control::WirelessNetworkInterface::OperationMode Solid::Control::AccessPoint::mode() const +{ + Q_D(const AccessPoint); + return_SOLID_CALL(Ifaces::AccessPoint *, d->backendObject(), (Solid::Control::WirelessNetworkInterface::OperationMode)0, mode()); +} + +int Solid::Control::AccessPoint::signalStrength() const +{ + Q_D(const AccessPoint); + return_SOLID_CALL(Ifaces::AccessPoint *, d->backendObject(), 0, signalStrength()); +} + +void Solid::Control::AccessPointPrivate::setBackendObject(QObject *object) +{ + FrontendObjectPrivate::setBackendObject(object); + + if (object) { + QObject::connect(object, SIGNAL(signalStrengthChanged(int)), + parent(), SIGNAL(signalStrengthChanged(int))); + QObject::connect(object, SIGNAL(bitRateChanged(int)), + parent(), SIGNAL(bitRateChanged(int))); + QObject::connect(object, SIGNAL(wpaFlagsChanged(Solid::Control::AccessPoint::WpaFlags)), + parent(), SIGNAL(wpaFlagsChanged(Solid::Control::AccessPoint::WpaFlags))); + QObject::connect(object, SIGNAL(rsnFlagsChanged(Solid::Control::AccessPoint::WpaFlags)), + parent(), SIGNAL(rsnFlagsChanged(Solid::Control::AccessPoint::WpaFlags))); + QObject::connect(object, SIGNAL(ssidChanged(const QString&)), + parent(), SIGNAL(ssidChanged(const QString&))); + QObject::connect(object, SIGNAL(frequencyChanged(uint)), + parent(), SIGNAL(frequencyChanged(uint))); + } +} + +void Solid::Control::AccessPoint::_k_destroyed(QObject *object) +{ + Q_UNUSED(object); + // nothing to do yet +} + +#include "wirelessaccesspoint.moc" diff --git a/solid/control/wirelessaccesspoint.h b/solid/control/wirelessaccesspoint.h new file mode 100644 index 000000000..00eed8963 --- /dev/null +++ b/solid/control/wirelessaccesspoint.h @@ -0,0 +1,186 @@ +/* +Copyright 2008 Will Stephenson + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) version 3, or any +later version accepted by the membership of KDE e.V. (or its +successor approved by the membership of KDE e.V.), which shall +act as a proxy defined in Section 6 of version 3 of the license. + +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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library. If not, see . +*/ + +#ifndef SOLID_CONTROL_WIRELESSAP_H +#define SOLID_CONTROL_WIRELESSAP_H + +#include + +#include "wirelessnetworkinterface.h" + +namespace Solid +{ +namespace Control +{ + class AccessPointPrivate; + class SOLIDCONTROL_EXPORT AccessPoint : public QObject + { + Q_OBJECT + Q_DECLARE_PRIVATE(AccessPoint) + Q_FLAGS(Capabilities WpaFlags) + public: + /** + * General capabilities of an access point + */ + enum Capability { Privacy = 0x1 }; + /** + * Flags describing the access point's capabilities according to WPA (Wifi Protected Access) + */ + enum WpaFlag { PairWep40 = 0x1, PairWep104 = 0x2, PairTkip = 0x4, PairCcmp = 0x8, + GroupWep40 = 0x10, GroupWep104 = 0x20, GroupTkip = 0x40, GroupCcmp = 0x80, + KeyMgmtPsk = 0x100, KeyMgmt8021x = 0x200 }; + Q_DECLARE_FLAGS(Capabilities, Capability) + Q_DECLARE_FLAGS(WpaFlags, WpaFlag) + + /** + * Creates a new Network object. + * + * @param backendObject the network object provided by the backend + */ + AccessPoint(QObject *backendObject = 0); + /** + * Copy ctor + */ + AccessPoint(const AccessPoint &); + + virtual ~AccessPoint(); + + /** + * Opaque and unique string identifier for this access point + */ + QString uni() const; + + /** + * Flags describing the capabilities of the access point + */ + Solid::Control::AccessPoint::Capabilities capabilities() const; + + /** + * Flags describing the access point's capabilities according to WPA (Wifi Protected Access) + */ + Solid::Control::AccessPoint::WpaFlags wpaFlags() const; + + /** + * Flags describing the access point's capabilities according to RSN (Robust Secure Network) + * aka WPA2 + */ + Solid::Control::AccessPoint::WpaFlags rsnFlags() const; + + /** + * The Service Set Identifier of the access point + */ + QString ssid() const; + + /** + * Retrieves the frequency in MHz of the radio channel that this access point is operating on + * + * @return the frequency + */ + uint frequency() const; + + /** + * The hardware address assigned to the access point's wireless interface + */ + QString hardwareAddress() const; + + /** + * Retrieves the maximum bit rate currently attainable with this access point + * + * @return the maximum bitrate in kilobit/s + */ + uint maxBitRate() const; + + /** + * Retrieves the operation mode of this access point + * + * @return the current mode + * @see Solid::Control::WirelessNetworkInterface::OperationMode + */ + Solid::Control::WirelessNetworkInterface::OperationMode mode() const; + + /** + * Retrieves the current signal strength of this wifi network. + * + * @return the signal strength as a percentage + */ + int signalStrength() const; + + Q_SIGNALS: + /** + * This signal is emitted when the signal strength of this network has changed. + * + * @param strength the new signal strength value for this network + */ + void signalStrengthChanged(int strength); + + /** + * This signal is emitted when the bitrate of this network has changed. + * + * @param bitrate the new bitrate value for this network + */ + void bitRateChanged(int bitrate); + + /** + * This signal is emitted when the WPA flags in use by this access point change + * + * @param flags the new flags + */ + void wpaFlagsChanged(Solid::Control::AccessPoint::WpaFlags flags) const; + + /** + * This signal is emitted when the RSN(WPA2) flags in use by this access point change + * + * @param flags the new flags + */ + void rsnFlagsChanged(Solid::Control::AccessPoint::WpaFlags flags) const; + /** + * This signal is emitted when the ssid of this Access Point changes + * + * @param ssid the new SSID + */ + void ssidChanged(const QString & ssid) const; + + /** + * This signal is emitted when the frequency used by this Access Point changes + * + * @param frequency the new frequency + */ + void frequencyChanged(uint frequency) const; + protected: + /** + * @internal + */ + AccessPoint(AccessPointPrivate &dd, QObject *backendObject); + /** + * @internal + */ + AccessPoint(AccessPointPrivate &dd, const AccessPoint & ap); + AccessPointPrivate * d_ptr; + private Q_SLOTS: + void _k_destroyed(QObject *object); + }; + typedef QStringList AccessPointList; +} // Control +} // Solid + +Q_DECLARE_OPERATORS_FOR_FLAGS(Solid::Control::AccessPoint::Capabilities) +Q_DECLARE_OPERATORS_FOR_FLAGS(Solid::Control::AccessPoint::WpaFlags) +#endif // SOLID_CONTROL_WIRELESSAP_H + diff --git a/solid/control/wirelessnetworkinterface.cpp b/solid/control/wirelessnetworkinterface.cpp new file mode 100644 index 000000000..22ece91dc --- /dev/null +++ b/solid/control/wirelessnetworkinterface.cpp @@ -0,0 +1,238 @@ +/* This file is part of the KDE project + Copyright (C) 2006 Will Stephenson + Copyright (C) 2007 Kevin Ottens + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#include "wirelessnetworkinterface.h" +#include "wirelessnetworkinterface_p.h" + +#include "soliddefs_p.h" +#include "wirelessaccesspoint.h" +#include "ifaces/wirelessaccesspoint.h" +#include "ifaces/wirelessnetworkinterface.h" + +Solid::Control::WirelessNetworkInterface::WirelessNetworkInterface(QObject *backendObject) + : NetworkInterface(*new WirelessNetworkInterfacePrivate(this), backendObject) +{ + Q_D(WirelessNetworkInterface); + d->setBackendObject(backendObject); + makeConnections( backendObject ); + d->readAccessPoints(); +} + +Solid::Control::WirelessNetworkInterface::WirelessNetworkInterface(const WirelessNetworkInterface &networkinterface) + : NetworkInterface(*new WirelessNetworkInterfacePrivate(this), networkinterface) +{ + Q_D(WirelessNetworkInterface); + d->setBackendObject(networkinterface.d_ptr->backendObject()); + makeConnections( networkinterface.d_ptr->backendObject() ); + d->readAccessPoints(); +} + +Solid::Control::WirelessNetworkInterface::WirelessNetworkInterface(WirelessNetworkInterfacePrivate &dd, QObject *backendObject) + : NetworkInterface(dd, backendObject) +{ + Q_D(WirelessNetworkInterface); + makeConnections( backendObject ); + d->readAccessPoints(); +} + +Solid::Control::WirelessNetworkInterface::WirelessNetworkInterface(WirelessNetworkInterfacePrivate &dd, const WirelessNetworkInterface &networkinterface) + : NetworkInterface(dd, networkinterface.d_ptr->backendObject()) +{ + Q_D(WirelessNetworkInterface); + makeConnections( networkinterface.d_ptr->backendObject() ); + d->readAccessPoints(); +} + +Solid::Control::WirelessNetworkInterface::~WirelessNetworkInterface() +{ + +} + +Solid::Control::NetworkInterface::Type Solid::Control::WirelessNetworkInterface::type() const +{ + return Ieee80211; +} + +void Solid::Control::WirelessNetworkInterface::makeConnections(QObject * source) +{ + connect(source, SIGNAL(accessPointAppeared(const QString &)), + this, SLOT(_k_accessPointAdded(const QString &))); + connect(source, SIGNAL(accessPointDisappeared(const QString &)), + this, SLOT(_k_accessPointRemoved(const QString &))); + connect(source, SIGNAL(bitRateChanged(int)), + this, SIGNAL(bitRateChanged(int))); + connect(source, SIGNAL(activeAccessPointChanged(const QString&)), + this, SIGNAL(activeAccessPointChanged(const QString&))); + connect(source, SIGNAL(modeChanged(Solid::Control::WirelessNetworkInterface::OperationMode)), + this, SIGNAL(modeChanged(Solid::Control::WirelessNetworkInterface::OperationMode))); +} + +QString Solid::Control::WirelessNetworkInterface::hardwareAddress() const +{ + Q_D(const WirelessNetworkInterface); + return_SOLID_CALL(Ifaces::WirelessNetworkInterface *, d->backendObject(), QString(), hardwareAddress()); +} + +QString Solid::Control::WirelessNetworkInterface::activeAccessPoint() const +{ + Q_D(const WirelessNetworkInterface); + return_SOLID_CALL(Ifaces::WirelessNetworkInterface *, d->backendObject(), QString(), activeAccessPoint()); +} + +int Solid::Control::WirelessNetworkInterface::bitRate() const +{ + Q_D(const WirelessNetworkInterface); + return_SOLID_CALL(Ifaces::WirelessNetworkInterface *, d->backendObject(), 0, bitRate()); +} + +Solid::Control::WirelessNetworkInterface::OperationMode Solid::Control::WirelessNetworkInterface::mode() const +{ + Q_D(const WirelessNetworkInterface); + return_SOLID_CALL(Ifaces::WirelessNetworkInterface *, d->backendObject(), (Solid::Control::WirelessNetworkInterface::OperationMode)0, mode()); +} + +Solid::Control::WirelessNetworkInterface::Capabilities Solid::Control::WirelessNetworkInterface::wirelessCapabilities() const +{ + Q_D(const WirelessNetworkInterface); + return_SOLID_CALL(Ifaces::WirelessNetworkInterface *, d->backendObject(), (Solid::Control::WirelessNetworkInterface::Capabilities)0, wirelessCapabilities()); +} + +Solid::Control::AccessPoint * Solid::Control::WirelessNetworkInterface::findAccessPoint(const QString & uni) const +{ + const AccessPointPair pair = findRegisteredAccessPoint(uni); + return pair.first; +} + +void Solid::Control::WirelessNetworkInterfacePrivate::setBackendObject(QObject *object) +{ + NetworkInterfacePrivate::setBackendObject(object); + + if (object) { + } +} + +Solid::Control::AccessPointList Solid::Control::WirelessNetworkInterface::accessPoints() const +{ + Q_D(const WirelessNetworkInterface); + return d->apMap.keys(); +} + +void Solid::Control::WirelessNetworkInterface::_k_accessPointAdded(const QString & uni) +{ + Q_D(WirelessNetworkInterface); + AccessPointMap::Iterator mapIt = d->apMap.find(uni); + + if (mapIt != d->apMap.end()) + { + // Oops, I'm not sure it should happen... + // But for an unknown reason it does + // We were deleting the existing items here, which caused problems later + // when the client calls find AccessPoint and gets a frontend object with a + // null private object - dangling pointer + } else { + mapIt = d->apMap.insert(uni, AccessPointPair(0, 0)); + } + + emit accessPointAppeared(uni); +} + +void Solid::Control::WirelessNetworkInterface::_k_accessPointRemoved(const QString & uni) +{ + Q_D(WirelessNetworkInterface); + AccessPointPair pair = d->apMap.take(uni); + + if (pair.first!= 0) + { + delete pair.first; + delete pair.second; + } + + emit accessPointDisappeared(uni); +} + +void Solid::Control::WirelessNetworkInterface::_k_destroyed(QObject *object) +{ + Q_D(WirelessNetworkInterface); + Ifaces::AccessPoint *ap = qobject_cast(object); + + if (ap!=0) + { + QString uni = ap->uni(); + AccessPointPair pair = d->apMap.take(uni); + delete pair.first; + } +} + +Solid::Control::AccessPointPair +Solid::Control::WirelessNetworkInterface::findRegisteredAccessPoint(const QString &uni) const +{ + Q_D(const WirelessNetworkInterface); + + AccessPointMap::ConstIterator mapIt = d->apMap.find(uni); + if (mapIt != d->apMap.end() && mapIt.value().second) { + return mapIt.value(); + } else { + AccessPointPair pair = d->createAP(uni); + if (pair.first && pair.second) { + d->apMap[uni] = pair; + } + return pair; + } + + return AccessPointPair(0, 0); +} + +void Solid::Control::WirelessNetworkInterfacePrivate::readAccessPoints() +{ + Ifaces::WirelessNetworkInterface * t = qobject_cast(backendObject()); + if (t != 0) + { + const MacAddressList unis = t->accessPoints(); + Q_FOREACH (const QString & uni, unis) { + apMap[uni] = AccessPointPair(0, 0); + } + } +} + +Solid::Control::AccessPointPair +Solid::Control::WirelessNetworkInterfacePrivate::createAP(const QString &uni) const +{ + Ifaces::WirelessNetworkInterface *device = qobject_cast(backendObject()); + AccessPoint *ap = 0; + + if (device!=0) { + Ifaces::AccessPoint *iface = qobject_cast(device->createAccessPoint(uni)); + + if (qobject_cast(iface)!=0) { + ap = new AccessPoint(iface); + } + + if (ap != 0) { + AccessPointPair pair(ap, iface); + QObject::connect(iface, SIGNAL(destroyed(QObject *)), + parent(), SLOT(_k_destroyed(QObject *))); + + return pair; + } + } + return AccessPointPair(0, 0); +} + +#include "wirelessnetworkinterface.moc" diff --git a/solid/control/wirelessnetworkinterface.h b/solid/control/wirelessnetworkinterface.h new file mode 100644 index 000000000..f13de3e97 --- /dev/null +++ b/solid/control/wirelessnetworkinterface.h @@ -0,0 +1,174 @@ +/* This file is part of the KDE project + Copyright (C) 2006 Will Stephenson + Copyright (C) 2007 Kevin Ottens + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#ifndef SOLID_CONTROL_WIRELESSNETWORKINTERFACE_H +#define SOLID_CONTROL_WIRELESSNETWORKINTERFACE_H + +#include "solid_control_export.h" + +#include "networkinterface.h" + +typedef QStringList AccessPointList; +namespace Solid +{ +namespace Control +{ + class AccessPoint; + class WirelessNetworkInterfacePrivate; +namespace Ifaces +{ + class AccessPoint; +} + + /** + * This interface represents a wireless network interface + */ + class SOLIDCONTROL_EXPORT WirelessNetworkInterface : public NetworkInterface + { + Q_OBJECT + Q_ENUMS(OperationMode DeviceInterface) + Q_FLAGS(Capabilities) + Q_DECLARE_PRIVATE(WirelessNetworkInterface) + + public: + enum OperationMode { Unassociated, Adhoc, Managed, Master, Repeater }; + // corresponding to 802.11 capabilities defined in NetworkManager.h + enum Capability { NoCapability = 0x0, Wep40 = 0x2, Wep104, Tkip = 0x4, Ccmp = 0x8, Wpa = 0x10, + Rsn }; + Q_DECLARE_FLAGS(Capabilities, Capability) + + /** + * Creates a new WirelessNetworkInterface object. + * + * @param backendObject the network object provided by the backend + */ + WirelessNetworkInterface(QObject *backendObject = 0); + + /** + * Constructs a copy of a network. + * + * @param network the network to copy + */ + WirelessNetworkInterface(const WirelessNetworkInterface &network); + + /** + * Destroys a WirelessNetworkInterface object. + */ + virtual ~WirelessNetworkInterface(); + + /** + * The NetworkInterface type. + * + * @return the NetworkInterface::Type. This always returns NetworkInterface::Ieee80211 + */ + virtual NetworkInterface::Type type() const; + + /** + * List of wireless networks currently visible to the hardware + */ + AccessPointList accessPoints() const; + + /** + * Identifier of the network this interface is currently associated with + */ + QString activeAccessPoint() const; + + /** + * The hardware address assigned to the network interface + */ + QString hardwareAddress() const; + + /** + * Retrieves the operation mode of this network. + * + * @return the current mode + * @see Solid::Control::WirelessNetworkInterface::OperationMode + */ + Solid::Control::WirelessNetworkInterface::OperationMode mode() const; + + /** + * Retrieves the effective bit rate currently attainable by this device. + * + * @return the bitrate in bit/s + */ + int bitRate() const; + + /** + * Retrieves the capabilities of this wifi network. + * + * @return the flag set describing the capabilities + * @see Solid::Control::WirelessNetworkInterface::DeviceInterface + */ + Solid::Control::WirelessNetworkInterface::Capabilities wirelessCapabilities() const; + + /** + * Finds access point object given its Unique Network Identifier. + * + * @param uni the identifier of the AP to find from this network interface + * @returns a valid AccessPoint object if a network having the given UNI for this device is known to the system, 0 otherwise + */ + AccessPoint *findAccessPoint(const QString & uni) const; + + Q_SIGNALS: + /** + * This signal is emitted when the bitrate of this network has changed. + * + * @param bitrate the new bitrate value for this network + */ + void bitRateChanged(int); + /** + * The active network changed. + */ + void activeAccessPointChanged(const QString &); + /** + * The device switched operating mode. + */ + void modeChanged(Solid::Control::WirelessNetworkInterface::OperationMode); + /** + * A new wireless access point appeared + */ + void accessPointAppeared(const QString &); + /** + * A wireless access point disappeared + */ + void accessPointDisappeared(const QString &); + protected: + /** + * @internal + */ + WirelessNetworkInterface(WirelessNetworkInterfacePrivate &dd, QObject *backendObject); + + /** + * @internal + */ + WirelessNetworkInterface(WirelessNetworkInterfacePrivate &dd, const WirelessNetworkInterface &network); + + void makeConnections(QObject * source); + QPair findRegisteredAccessPoint(const QString &uni) const; + private Q_SLOTS: + void _k_accessPointAdded(const QString &uni); + void _k_accessPointRemoved(const QString &uni); + void _k_destroyed(QObject *object); + }; +} //Control +} //Solid + +#endif //SOLID_CONTROL_WIREDNETWORKINTERFACE_H + diff --git a/solid/control/wirelessnetworkinterface_p.h b/solid/control/wirelessnetworkinterface_p.h new file mode 100644 index 000000000..ab2d4ce9e --- /dev/null +++ b/solid/control/wirelessnetworkinterface_p.h @@ -0,0 +1,58 @@ +/* This file is part of the KDE project + Copyright (C) 2006 Will Stephenson + Copyright (C) 2007 Kevin Ottens + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#ifndef SOLID_NETWORK_P_H +#define SOLID_NETWORK_P_H + +#include "networkinterface_p.h" + +namespace Solid +{ +namespace Control +{ + class AccessPoint; +namespace Ifaces +{ + class AccessPoint; +} + + typedef QPair AccessPointPair; + typedef QMap AccessPointMap; + + + class WirelessNetworkInterfacePrivate : public NetworkInterfacePrivate + { + public: + explicit WirelessNetworkInterfacePrivate(QObject *parent) + : NetworkInterfacePrivate(parent) { } + + void setBackendObject(QObject *object); + + //Solid::Control::AccessPoint *findRegisteredAccessPoint(const QString &uni) const; + void readAccessPoints(); + AccessPointPair createAP(const QString &uni) const; + + //mutable QMap apMap; + mutable AccessPointMap apMap; + }; +} +} + +#endif diff --git a/taskmanager/CMakeLists.txt b/taskmanager/CMakeLists.txt new file mode 100644 index 000000000..3cdd7537a --- /dev/null +++ b/taskmanager/CMakeLists.txt @@ -0,0 +1,55 @@ + + + +########### next target ############### + +set(taskmanager_LIB_SRCS + abstractgroupableitem.cpp + abstractgroupingstrategy.cpp + abstractsortingstrategy.cpp + groupmanager.cpp + startup.cpp + strategies/alphasortingstrategy.cpp + strategies/programgroupingstrategy.cpp + strategies/manualgroupingstrategy.cpp + strategies/manualsortingstrategy.cpp + task.cpp + taskactions.cpp + taskgroup.cpp + taskitem.cpp + taskmanager.cpp + taskrmbmenu.cpp + ) + +kde4_add_library(taskmanager SHARED ${taskmanager_LIB_SRCS}) + +target_link_libraries(taskmanager ${KDE4_KDEUI_LIBS} ${X11_LIBRARIES}) +if (X11_Xfixes_FOUND) + target_link_libraries(taskmanager ${X11_Xfixes_LIB}) +endif (X11_Xfixes_FOUND) +if (X11_Xrender_FOUND) + target_link_libraries(taskmanager ${X11_Xrender_LIB}) +endif (X11_Xrender_FOUND) +if (X11_Xcomposite_FOUND) + target_link_libraries(taskmanager ${X11_Xcomposite_LIB}) +endif (X11_Xcomposite_FOUND) + +set_target_properties(taskmanager PROPERTIES VERSION ${GENERIC_LIB_VERSION} SOVERSION ${GENERIC_LIB_SOVERSION} ) +install(TARGETS taskmanager ${INSTALL_TARGETS_DEFAULT_ARGS} ) + +install(FILES + abstractgroupableitem.h + abstractgroupingstrategy.h + abstractsortingstrategy.h + groupmanager.h + startup.h + task.h + taskactions.h + taskgroup.h + taskitem.h + taskmanager.h + taskmanager_export.h + DESTINATION ${INCLUDE_INSTALL_DIR}/taskmanager COMPONENT Devel + ) + + diff --git a/taskmanager/Mainpage.dox b/taskmanager/Mainpage.dox new file mode 100644 index 000000000..11dbb7f2e --- /dev/null +++ b/taskmanager/Mainpage.dox @@ -0,0 +1,21 @@ +/** @mainpage Task management library + +This directory contains the classes making up libtaskmanager, which +provides task management facilities such as might be useful for a +taskbar implementation. + +@authors +Matthias Elter \ +Richard Moore \ +John Firebaugh \ + +@maintainers +Aaron Seigo \ + +@licenses +@lgpl + +*/ + +// DOXYGEN_SET_PROJECT_NAME = libtaskmanager +// vim:ts=4:sw=4:expandtab:filetype=doxygen diff --git a/taskmanager/Messages.sh b/taskmanager/Messages.sh new file mode 100644 index 000000000..8b5ec798f --- /dev/null +++ b/taskmanager/Messages.sh @@ -0,0 +1,2 @@ +#! /usr/bin/env bash +$XGETTEXT *.cpp */*.cpp *.h -o $podir/libtaskmanager.pot diff --git a/taskmanager/abstractgroupableitem.cpp b/taskmanager/abstractgroupableitem.cpp new file mode 100644 index 000000000..106462c7b --- /dev/null +++ b/taskmanager/abstractgroupableitem.cpp @@ -0,0 +1,118 @@ +/***************************************************************** + +Copyright 2008 Christian Mollekopf + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************/ + +// Ownm_preferredInsertIndex +#include "abstractgroupableitem.h" +#include "taskgroup.h" +#include "taskmanager.h" + + +// KDE +#include + + + +namespace TaskManager +{ + + +class AbstractGroupableItem::Private +{ +public: + Private() + :m_parentGroup(0) + { + } + + GroupPtr m_parentGroup; +}; + + +AbstractGroupableItem::AbstractGroupableItem(QObject *parent) +: QObject(parent), + d(new Private) +{ + +} + + +AbstractGroupableItem::~AbstractGroupableItem() +{ + //kDebug(); + emit destroyed(this); + /*if (parentGroup()) { + kDebug() << "Error: item gets destroyed but still has a parent group"; + }*/ + delete d; +} + + +bool AbstractGroupableItem::isGrouped() const +{ + return parentGroup() && parentGroup()->parentGroup(); +} + +QIcon AbstractGroupableItem::icon() const +{ + return QIcon(); +} + +QString AbstractGroupableItem::name() const +{ + return QString(); +} + +GroupPtr AbstractGroupableItem::parentGroup() const +{ + //kDebug(); + return d->m_parentGroup; +} + + +void AbstractGroupableItem::setParentGroup(const GroupPtr group) +{ + d->m_parentGroup = group; +} + + +//Item is member of group +bool AbstractGroupableItem::isGroupMember(const GroupPtr group) const +{ + kDebug(); + if (!group) { + kDebug() << "Null Group Pointer"; + return false; + } + + if (!parentGroup()) { + return false; + } + + return group->members().contains(const_cast(this)); +} + + +} // TaskManager namespace + +#include "abstractgroupableitem.moc" + diff --git a/taskmanager/abstractgroupableitem.h b/taskmanager/abstractgroupableitem.h new file mode 100644 index 000000000..91b8c0036 --- /dev/null +++ b/taskmanager/abstractgroupableitem.h @@ -0,0 +1,127 @@ +/***************************************************************** + +Copyright 2008 Christian Mollekopf + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************/ + +#ifndef ABSTRACTGROUPABLEITEM_H +#define ABSTRACTGROUPABLEITEM_H + +#include +#include + +#include + +#include +#include + +namespace TaskManager +{ + +class TaskGroup; +class AbstractGroupableItem; + +typedef AbstractGroupableItem* AbstractItemPtr; +typedef TaskGroup* GroupPtr; + +typedef QList ItemList; +typedef QList GroupList; + +/** + * Abstract Class for an Item that is groupable + * So groups can handle tasks and subgroups the same way + */ +class TASKMANAGER_EXPORT AbstractGroupableItem : public QObject +{ + Q_OBJECT +public: + AbstractGroupableItem(QObject *parent); + virtual ~AbstractGroupableItem(); + + virtual QIcon icon() const; + virtual QString name() const; + + /** + * Returns the parent group of this item + */ + GroupPtr parentGroup() const; + + /** + * Not only member of rootGroup + */ + bool isGrouped() const; + + bool isGroupMember(const GroupPtr group) const; + virtual bool isGroupItem() const = 0; + + virtual bool isOnCurrentDesktop() const = 0; + virtual bool isOnAllDesktops() const = 0; + virtual int desktop() const = 0; + virtual bool isShaded() const = 0; + virtual bool isMaximized() const = 0; + virtual bool isMinimized() const = 0; + virtual bool isFullScreen() const = 0; + virtual bool isKeptBelowOthers() const = 0; + virtual bool isAlwaysOnTop() const = 0; + virtual bool isActionSupported(NET::Action) const = 0; + virtual bool isActive() const = 0; + virtual bool demandsAttention() const = 0; + + +public Q_SLOTS: + /** Functions that both, Tasks and Groups have */ + virtual void toDesktop(int) = 0; + + virtual void setShaded(bool) = 0; + virtual void toggleShaded() = 0; + + virtual void setMaximized(bool) = 0; + virtual void toggleMaximized() = 0; + + virtual void setMinimized(bool) = 0; + virtual void toggleMinimized() = 0; + + virtual void setFullScreen(bool) = 0; + virtual void toggleFullScreen() = 0; + + virtual void setKeptBelowOthers(bool) = 0; + virtual void toggleKeptBelowOthers() = 0; + + virtual void setAlwaysOnTop(bool) = 0; + virtual void toggleAlwaysOnTop() = 0; + + virtual void close() = 0; + + void setParentGroup(const GroupPtr group); + /*void removedFromGroup(); + void addedToGroup(const GroupPtr group);*/ + +Q_SIGNALS: + void changed(::TaskManager::TaskChanges changes); + void destroyed(AbstractGroupableItem *); + +private: + class Private; + Private * const d; +}; + +} // TaskManager namespace + +#endif diff --git a/taskmanager/abstractgroupingstrategy.cpp b/taskmanager/abstractgroupingstrategy.cpp new file mode 100644 index 000000000..5d3de8586 --- /dev/null +++ b/taskmanager/abstractgroupingstrategy.cpp @@ -0,0 +1,240 @@ +/***************************************************************** + +Copyright 2008 Christian Mollekopf + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************/ + +#include "abstractgroupingstrategy.h" + +#include +#include + +#include "task.h" + +namespace TaskManager +{ + +class AbstractGroupingStrategy::Private +{ +public: + Private() + : type(GroupManager::NoGrouping) + { + } + + GroupManager *groupManager; + QStringList usedNames; + QList usedColors; + QList createdGroups; + GroupManager::TaskGroupingStrategy type; +}; + + +AbstractGroupingStrategy::AbstractGroupingStrategy(GroupManager *groupManager) + : QObject(groupManager), + d(new Private) +{ + d->groupManager = groupManager; +} + +AbstractGroupingStrategy::~AbstractGroupingStrategy() +{ + foreach (TaskGroup *group, d->createdGroups) { //cleanup all created groups + closeGroup(group); + } + delete d; +} + +GroupManager::TaskGroupingStrategy AbstractGroupingStrategy::type() const +{ + return d->type; +} + +void AbstractGroupingStrategy::setType(GroupManager::TaskGroupingStrategy type) +{ + d->type = type; +} + +void AbstractGroupingStrategy::desktopChanged(int newDesktop) +{ + Q_UNUSED(newDesktop) +} + +QList AbstractGroupingStrategy::strategyActions(QObject *parent, AbstractGroupableItem *item) +{ + Q_UNUSED(parent) + Q_UNUSED(item) + return QList(); +} + + +TaskGroup* AbstractGroupingStrategy::createGroup(ItemList items) +{ + kDebug(); + GroupPtr oldGroup; + if (items.first()->isGrouped()) { + oldGroup = items.first()->parentGroup(); + } else { + oldGroup = d->groupManager->rootGroup(); + } + + TaskGroup *newGroup = new TaskGroup(d->groupManager); + d->createdGroups.append(newGroup); + connect(newGroup, SIGNAL(itemRemoved(AbstractItemPtr)), this, SLOT(checkGroup())); + foreach (AbstractItemPtr item, items) { + newGroup->add(item); + } + oldGroup->add(newGroup); + return newGroup; +} + +void AbstractGroupingStrategy::closeGroup(TaskGroup *group) +{ + Q_ASSERT(group); + disconnect(group, 0, this, 0); + kDebug(); + d->createdGroups.removeAll(group); + d->usedNames.removeAll(group->name()); + d->usedColors.removeAll(group->color()); + //d->usedIcons.removeAll(group->icon());//TODO + if (group->parentGroup()) { + foreach (AbstractItemPtr item, group->members()) { + group->parentGroup()->add(item); + } + group->parentGroup()->remove(group); + } else { + foreach (AbstractItemPtr item, group->members()) { + d->groupManager->rootGroup()->add(item); + } + //group->clear(); + } + group->deleteLater(); +} + +void AbstractGroupingStrategy::checkGroup() +{ + TaskGroup *group = qobject_cast(sender()); + if (!group) { + return; + } + + if (group->members().size() <= 0) { + closeGroup(group); + } +} + +bool AbstractGroupingStrategy::addItemToGroup(AbstractGroupableItem *item, TaskGroup *group) +{ + if (editableGroupProperties() & Members) { + group->add(item); + return true; + } + + return false; +} + +bool AbstractGroupingStrategy::setName(const QString &name, TaskGroup *group) +{ + d->usedNames.removeAll(group->name()); + if ((editableGroupProperties() & Name) && (!d->usedNames.contains(name))) { + //TODO editableGroupProperties shouldn't be tested here i think + d->usedNames.append(name); + group->setName(name); + return true; + } + return false; +} + +//Returns 6 free names +QList AbstractGroupingStrategy::nameSuggestions(TaskGroup *) +{ + QList nameList; + int i = 1; + + while (nameList.count() < 6) { + if (!d->usedNames.contains("Group"+QString::number(i))) { + nameList.append("Group"+QString::number(i)); + } + i++; + } + + if (nameList.isEmpty()) { + nameList.append("default"); + } + + return nameList; +} + +bool AbstractGroupingStrategy::setColor(const QColor &color, TaskGroup *group) +{ + d->usedColors.removeAll(group->color()); + + if (editableGroupProperties() && (!d->usedColors.contains(color))) { + d->usedColors.append(color); + group->setColor(color); + return true; + } + + return false; +} + +QList AbstractGroupingStrategy::colorSuggestions(TaskGroup *) +{ + QList colorPool; + //colorPool.append(Qt::red); + colorPool.append(Qt::blue); + colorPool.append(Qt::green); + colorPool.append(Qt::yellow); + + QList colorList; + foreach (QColor color, colorPool) { + if (!d->usedColors.contains(color)) { + colorList.append(color); + } + } + + if (colorList.isEmpty()) { + colorList.append(Qt::red); + } + + return colorList; +} + +bool AbstractGroupingStrategy::setIcon(const QIcon &icon, TaskGroup *group) +{ + if (editableGroupProperties() & Icon) { + group->setIcon(icon); + return true; + } + + return false; +} + +QList AbstractGroupingStrategy::iconSuggestions(TaskGroup *) +{ + QList iconList; + iconList.append(KIcon("xorg")); + return iconList; +} + +}//namespace + +#include "abstractgroupingstrategy.moc" + diff --git a/taskmanager/abstractgroupingstrategy.h b/taskmanager/abstractgroupingstrategy.h new file mode 100644 index 000000000..39baa4fa0 --- /dev/null +++ b/taskmanager/abstractgroupingstrategy.h @@ -0,0 +1,115 @@ +/***************************************************************** + +Copyright 2008 Christian Mollekopf + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************/ + +#ifndef ABSTRACTGROUPINGSTRATEGY_H +#define ABSTRACTGROUPINGSTRATEGY_H + +#include + +#include +#include +#include +#include + +class QAction; + +namespace TaskManager +{ + +/** + * Base class for strategies which can be used to + * automatically group tasks. + */ +class TASKMANAGER_EXPORT AbstractGroupingStrategy : public QObject +{ + Q_OBJECT +public: + AbstractGroupingStrategy(GroupManager *groupManager); + virtual ~AbstractGroupingStrategy(); + + /** Handles a new item */ + virtual void handleItem(AbstractItemPtr) = 0; + + /** Returns the strategy type */ + GroupManager::TaskGroupingStrategy type() const; + + /** DesktopChanges time to backup any needed data */ + virtual void desktopChanged(int newDesktop); + + /** Returns list of actions that a task can do in this groupingStrategy + * If the visualization supports grouping it has to show these actions. + */ + virtual QList strategyActions(QObject *parent, AbstractGroupableItem *item); + + enum EditableGroupProperties + { + None = 0, + Name = 1, + Color = 2, + Icon = 4, + Members = 8, + All = 15 + }; + /** Returns which group properties are editable by the user and which are handled solely by the strategy. + * The visualization should create a configuration interface based on this. + */ + virtual EditableGroupProperties editableGroupProperties() = 0; + + /** The following functions check if a property is editable and sets it on group*/ + + /** Adds an item to group if EditableGroupProperties::Members is set*/ + virtual bool addItemToGroup(AbstractGroupableItem *, TaskGroup*); + + virtual bool setName(const QString &, TaskGroup*); + /** Returns a List of unused Names*/ + virtual QList nameSuggestions(TaskGroup *); + + virtual bool setColor(const QColor &, TaskGroup*); + /** Returns a list of unused colors*/ + virtual QList colorSuggestions(TaskGroup *); + + virtual bool setIcon(const QIcon &, TaskGroup*); + /** Returns a list of icons*/ + virtual QList iconSuggestions(TaskGroup *); + +protected Q_SLOTS: + /** Adds all group members to the parentgroup of group and removes the group */ + virtual void closeGroup(TaskGroup *group); + + /** Checks if the group is still necessary, removes group if empty*/ + virtual void checkGroup(); + + /** Returns the strategy type */ + void setType(GroupManager::TaskGroupingStrategy type); + +protected: + /** Create a group with items and returns the newly created group */ + TaskGroup* createGroup(ItemList items); + +private: + class Private; + Private * const d; +}; + +} // TaskManager namespace +#endif diff --git a/taskmanager/abstractsortingstrategy.cpp b/taskmanager/abstractsortingstrategy.cpp new file mode 100644 index 000000000..5641f9b39 --- /dev/null +++ b/taskmanager/abstractsortingstrategy.cpp @@ -0,0 +1,176 @@ +/***************************************************************** + +Copyright 2008 Christian Mollekopf + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************/ + +#include "abstractsortingstrategy.h" + +#include "taskitem.h" +#include "taskgroup.h" +#include "taskmanager.h" + +#include +#include + +#include + + +namespace TaskManager +{ + +class AbstractSortingStrategy::Private +{ +public: + Private() + : type(GroupManager::NoSorting) + { + } + + QList managedGroups; + GroupManager::TaskSortingStrategy type; +}; + + +AbstractSortingStrategy::AbstractSortingStrategy(QObject *parent) + :QObject(parent), + d(new Private) +{ + +} + +AbstractSortingStrategy::~AbstractSortingStrategy() +{ + delete d; +} + +GroupManager::TaskSortingStrategy AbstractSortingStrategy::type() const +{ + return d->type; +} + +void AbstractSortingStrategy::setType(GroupManager::TaskSortingStrategy type) +{ + d->type = type; +} + +void AbstractSortingStrategy::handleGroup(TaskGroup *group) +{ + if (d->managedGroups.contains(group) || !group) { + return; + } + d->managedGroups.append(group); + disconnect(group, 0, this, 0); //To avoid duplicate connections + connect(group, SIGNAL(itemAdded(AbstractItemPtr)), this, SLOT(handleItem(AbstractItemPtr))); + connect(group, SIGNAL(destroyed()), this, SLOT(removeGroup())); //FIXME necessary? + foreach (AbstractItemPtr item, group->members()) { + handleItem(item); + } +} + +void AbstractSortingStrategy::removeGroup() +{ + TaskGroup *group = dynamic_cast(sender()); + + if (!group) { + return; + } + + d->managedGroups.removeAll(group); +} + +void AbstractSortingStrategy::handleItem(AbstractItemPtr item) +{ + if (item->isGroupItem()) { + handleGroup(qobject_cast(item)); + } else if (!(qobject_cast(item))->task()) { //ignore startup tasks + return; + } + disconnect(item, 0, this, 0); //To avoid duplicate connections + // connect(item, SIGNAL(changed(::TaskManager::TaskChanges)), this, SLOT(check())); + check(item); +} + +void AbstractSortingStrategy::check(AbstractItemPtr itemToCheck) +{ + kDebug(); + AbstractItemPtr item; + if (!itemToCheck) { + //return; + item = dynamic_cast(sender()); + } else { + item = itemToCheck; + } + + if (!item) { + kDebug() << "invalid item"; + return; + } + + if (!item->isGroupItem()) { + if (!(qobject_cast(item))->task()) { //ignore startup tasks + return; + } + } + + if (!item->parentGroup()) { + kDebug() << "No parent group"; + return; + } + + ItemList sortedList = item->parentGroup()->members(); + sortItems(sortedList); + int oldIndex = item->parentGroup()->members().indexOf(item); + int newIndex = sortedList.indexOf(item); + if (oldIndex != newIndex) { + item->parentGroup()->moveItem(oldIndex, newIndex); + } +} + +void AbstractSortingStrategy::desktopChanged(int newDesktop) +{ + Q_UNUSED(newDesktop) +} + +bool AbstractSortingStrategy::moveItem(AbstractItemPtr item, int newIndex) +{ + kDebug() << "move to " << newIndex; + if (!item->parentGroup()) { + kDebug() << "error: no parentgroup but the item was asked to move"; + return false; + } + + const ItemList list = item->parentGroup()->members(); + if ((newIndex < 0) || (newIndex >= list.size())) { + newIndex = list.size(); + } + + int oldIndex = list.indexOf(item); + if (newIndex > oldIndex) { + newIndex--; //the index has to be adjusted if we move the item from right to left because the item on the left is removed first + } + + return item->parentGroup()->moveItem(oldIndex, newIndex); +} + +} //namespace + +#include "abstractsortingstrategy.moc" + diff --git a/taskmanager/abstractsortingstrategy.h b/taskmanager/abstractsortingstrategy.h new file mode 100644 index 000000000..9bd4076f1 --- /dev/null +++ b/taskmanager/abstractsortingstrategy.h @@ -0,0 +1,88 @@ +/***************************************************************** + +Copyright 2008 Christian Mollekopf + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************/ + +#ifndef ABSTRACTSORTINGSTRATEGY_H +#define ABSTRACTSORTINGSTRATEGY_H + +#include + +#include +#include +#include + +namespace TaskManager +{ + +/** + * Base class for strategies which can be used to + * automatically sort tasks. + */ +class TASKMANAGER_EXPORT AbstractSortingStrategy : public QObject +{ + Q_OBJECT +public: + AbstractSortingStrategy(QObject *parent); + virtual ~AbstractSortingStrategy(); + + /** Returns the strategy type */ + GroupManager::TaskSortingStrategy type() const; + + /** Adds group under control of sorting strategy. all added subgroups are automatically added to this sortingStrategy*/ + void handleGroup(TaskGroup *); + + /** DesktopChanges time to backup any needed data */ + virtual void desktopChanged(int newDesktop); + + /** Moves Item to new index*/ + bool moveItem(AbstractItemPtr, int); + +protected Q_SLOTS: + /** Handles a new item, is typically called after an item was added to a handled group*/ + virtual void handleItem(AbstractItemPtr); + /** Checks if the order has to be updated. Must be connected to a AbstractGroupableItem* */ + void check(AbstractItemPtr item = 0); + void removeGroup(); //FIXME necessary? + +protected: + void setType(GroupManager::TaskSortingStrategy strategy); + +private: + /** + * Sorts list of items according to startegy. + * Has to be reimplemented by every SortingStrategy. + * + * @param items the items that are to be sorted; the list is passed + * in by value and should be in the proprer sorting order when + * the method returns. + */ + virtual void sortItems(ItemList &ites) = 0; + + class Private; + Private * const d; +}; + +typedef QHash itemHashTable; +typedef QHash desktopHashTable; + +} // TaskManager namespace +#endif diff --git a/taskmanager/groupmanager.cpp b/taskmanager/groupmanager.cpp new file mode 100644 index 000000000..66cb84f6d --- /dev/null +++ b/taskmanager/groupmanager.cpp @@ -0,0 +1,627 @@ +/***************************************************************** + +Copyright 2008 Christian Mollekopf + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************/ + +#include "groupmanager.h" + +#include +#include +#include + + +#include "abstractsortingstrategy.h" +#include "startup.h" +#include "task.h" +#include "taskitem.h" +#include "taskgroup.h" +#include "taskmanager.h" +#include "strategies/alphasortingstrategy.h" +#include "strategies/programgroupingstrategy.h" +#include "strategies/manualgroupingstrategy.h" +#include "strategies/manualsortingstrategy.h" + +namespace TaskManager +{ + +class GroupManagerPrivate +{ +public: + GroupManagerPrivate(GroupManager *manager) + : q(manager), + rootGroup(0), + sortingStrategy(GroupManager::NoSorting), + groupingStrategy(GroupManager::NoGrouping), + abstractGroupingStrategy(0), + abstractSortingStrategy(0), + currentScreen(-1), + showOnlyCurrentDesktop(false), + showOnlyCurrentScreen(false), + showOnlyMinimized(false), + onlyGroupWhenFull(false), + groupIsFullLimit(0), + lastGroupingStrategy(GroupManager::NoGrouping) + { + } + + /** reload all tasks from TaskManager */ + void reloadTasks(); + + /** + * Keep track of changes in Taskmanager + */ + void currentDesktopChanged(int); + void taskChanged(TaskPtr, ::TaskManager::TaskChanges); + + void checkScreenChange(); + + void itemDestroyed(); + void checkIfFull(); + + GroupManager *q; + QHash itemList; //holds all tasks of the Taskmanager + QHash startupList; + TaskGroup *rootGroup; //the current layout + GroupManager::TaskSortingStrategy sortingStrategy; + GroupManager::TaskGroupingStrategy groupingStrategy; + AbstractGroupingStrategy *abstractGroupingStrategy; + AbstractSortingStrategy *abstractSortingStrategy; + int currentScreen; + QTimer screenTimer; + QList geometryTasks; + bool showOnlyCurrentDesktop : 1; + bool showOnlyCurrentScreen : 1; + bool showOnlyMinimized : 1; + bool onlyGroupWhenFull : 1; + int groupIsFullLimit; + GroupManager::TaskGroupingStrategy lastGroupingStrategy; +}; + + + + +GroupManager::GroupManager(QObject *parent) + : QObject(parent), + d(new GroupManagerPrivate(this)) +{ + connect(TaskManager::self(), SIGNAL(taskAdded(TaskPtr)), this, SLOT(add(TaskPtr))); + connect(TaskManager::self(), SIGNAL(taskRemoved(TaskPtr)), this, SLOT(remove(TaskPtr))); + connect(TaskManager::self(), SIGNAL(startupAdded(StartupPtr)), this, SLOT(add(StartupPtr))); + connect(TaskManager::self(), SIGNAL(startupRemoved(StartupPtr)), this, SLOT(remove(StartupPtr))); + d->rootGroup = new TaskGroup(this, "RootGroup", Qt::transparent); + //reloadTasks(); + d->screenTimer.setSingleShot(true); + d->screenTimer.setInterval(100); + connect(&d->screenTimer, SIGNAL(timeout()), this, SLOT(checkScreenChange())); +} + +GroupManager::~GroupManager() +{ + delete d->abstractSortingStrategy; + delete d->abstractGroupingStrategy; + delete d->rootGroup; + delete d; +} + +void GroupManagerPrivate::reloadTasks() +{ + //kDebug() << "number of tasks available " << TaskManager::self()->tasks().size(); + + QList taskList = TaskManager::self()->tasks().values(); + foreach(TaskPtr task, taskList) { //Add all existing tasks + if (!q->add(task)) { + q->remove(task); //remove what isn't needed anymore + } + taskList.removeAll(task); + } + + foreach(TaskPtr task, taskList) { //Remove the remaining + q->remove(task); + } + + emit q->reload(); +} + +void GroupManager::add(StartupPtr task) +{ + kDebug(); + TaskItem *item; + if (!d->startupList.contains(task)) { + item = new TaskItem(this,task); + d->startupList.insert(task, item); + d->rootGroup->add(item); + } +} + +void GroupManager::remove(StartupPtr task) +{ + kDebug() << "startup"; + AbstractItemPtr item = d->startupList.take(task); + if (!item) { + kDebug() << "invalid item"; + return; + } + + if (item->parentGroup()) { + item->parentGroup()->remove(item); + } + emit itemRemoved(item); + +} + +bool GroupManager::add(TaskPtr task) +{ + //kDebug(); + /*kDebug() << task->visibleName(); + kDebug() << task->visibleNameWithState(); + kDebug() << task->name(); + kDebug() << task->className(); + kDebug() << task->classClass();*/ + + // Go through all filters whether the task should be displayed or not + bool show = true; + if (!task->showInTaskbar()) { + kDebug() << "Do not show in taskbar"; + show = false; + } + + if (showOnlyCurrentDesktop() && !task->isOnCurrentDesktop()) { + kDebug() << "Not on this desktop and showOnlyCurrentDesktop"; + show = false; + } + + if (showOnlyCurrentScreen() && !task->isOnScreen(d->currentScreen)) { + kDebug() << "Not on this screen and showOnlyCurrentScreen"; + show = false; + } + + if (showOnlyMinimized() && !task->isMinimized()) { + show = false; + } + + NET::WindowType type = task->info().windowType(NET::NormalMask | NET::DialogMask | + NET::OverrideMask | NET::UtilityMask); + if (type == NET::Utility) { + kDebug() << "skipping utility window" << task->name(); + show = false; + } + + //TODO: should we check for transiency? if so the following code can detect it. + /* + QHash ::iterator it = d->itemList.begin(); + + while (it != d->itemList.end()) { + TaskItem *item = it.value(); + if (item->task()->hasTransient(task->window())) { + kDebug() << "TRANSIENT TRANSIENT TRANSIENT!"; + } + ++it; + } + */ + + if (task->demandsAttention()) { //override all other limitations + show = true; + } + + if (!show) { + return false; + } + //Ok the Task should be displayed + TaskItem *item = 0; + if (!d->itemList.contains(task)) { + //Lookout for existing startuptask of this task + QMutableHashIterator it(d->startupList); + while (it.hasNext()) { + it.next(); + if (it.key()->matchesWindow(task->window())) { + kDebug() << "startup task"; + item = it.value(); + item->setTaskPointer(task); + it.remove(); + break; + } + } + + if (!item) { + item = new TaskItem(this,task); + } + + connect(item, SIGNAL(destroyed()), this, SLOT(itemDestroyed())); + d->itemList.insert(task, item); + } else { + item = d->itemList.value(task); //we add it again so the group is evaluated again + } + + //Find a fitting group for the task with GroupingStrategies + if (d->abstractGroupingStrategy && !task->demandsAttention()) { //do not group attetion tasks + d->abstractGroupingStrategy->handleItem(item); + } else { + d->rootGroup->add(item); + } + return true; +} + + +void GroupManager::remove(TaskPtr task) +{ + //kDebug() << "remove: " << task->visibleName(); + TaskItem *item = d->itemList.value(task); + if (!item) { + kDebug() << "invalid item"; + return; + } + if (item->parentGroup()) { + item->parentGroup()->remove(item); + } + emit itemRemoved(item); + //the item must exist as long as the TaskPtr does because of activate calls so don't delete the item here, it will delete itself. We keep it in the itemlist because it may return + +} + +void GroupManagerPrivate::itemDestroyed() +{ + TaskItem *taskItem = qobject_cast(q->sender()); + TaskItem *item = itemList.take(itemList.key(taskItem)); + if (!item) { + kDebug() << "invalid item"; + return; + } + QObject::disconnect(item, 0, q, 0); +} + + +bool GroupManager::manualGroupingRequest(AbstractGroupableItem* item, TaskGroup* groupItem) +{ + kDebug(); + if (d->abstractGroupingStrategy) { + return d->abstractGroupingStrategy->addItemToGroup(item, groupItem); + // kDebug() << d->abstractGroupingStrategy->type() << ManualGrouping; + /*if (d->abstractGroupingStrategy->type() == ManualGrouping) { + // kDebug(); + return (qobject_cast(d->abstractGroupingStrategy))->addItemToGroup(item,groupItem); + }*/ + } + return false; +} + +bool GroupManager::manualGroupingRequest(ItemList items) +{ + kDebug(); + if (d->abstractGroupingStrategy) { + // kDebug() << d->abstractGroupingStrategy->type() << ManualGrouping; + if (d->abstractGroupingStrategy->type() == ManualGrouping) { + // kDebug(); + return (qobject_cast(d->abstractGroupingStrategy))->groupItems(items); + } + } + return false; +} + +bool GroupManager::manualSortingRequest(AbstractGroupableItem* taskItem, int newIndex) +{ + kDebug(); + if (d->abstractSortingStrategy) { + if (d->abstractSortingStrategy->type() == ManualSorting) { + return (qobject_cast(d->abstractSortingStrategy))->moveItem(taskItem, newIndex); + } + } + return false; +} + + +GroupPtr GroupManager::rootGroup() const +{ + return d->rootGroup; +} + + +void GroupManagerPrivate::currentDesktopChanged(int newDesktop) +{ + kDebug(); + if (!showOnlyCurrentDesktop) { + return; + } + + if (abstractSortingStrategy) { + abstractSortingStrategy->desktopChanged(newDesktop); + } + + if (abstractGroupingStrategy) { + abstractGroupingStrategy->desktopChanged(newDesktop); + } + + reloadTasks(); +} + + +void GroupManagerPrivate::taskChanged(TaskPtr task, ::TaskManager::TaskChanges changes) +{ + kDebug(); + bool takeAction = false; + bool show = true; + + if (showOnlyCurrentDesktop && changes & ::TaskManager::DesktopChanged) { + takeAction = true; + show = task->isOnCurrentDesktop(); + //kDebug() << task->visibleName() << "on" << TaskManager::self()->currentDesktop(); + } + + if (showOnlyMinimized && changes & ::TaskManager::StateChanged) { + //TODO: wouldn't it be nice to get notification of JUST minimization? + takeAction = true; + show = task->isMinimized(); + } + + if (changes & ::TaskManager::GeometryChanged) { + //kDebug() << "geomtery Changed"; + if (!geometryTasks.contains(task)) { + geometryTasks.append(task); + } + + if (!screenTimer.isActive()) { + screenTimer.start(); + } + } + + //show tasks anyway if they demand attention + if (changes & ::TaskManager::StateChanged && task->demandsAttention()) { + takeAction = true; + show = true; + } + + if (!takeAction) { + return; + } + + if (show) { + //kDebug() << "add(task);"; + q->add(task); + } else { + //kDebug() << "remove(task);"; + q->remove(task); + } +} + +void GroupManager::setScreen(int screen) +{ + kDebug() << "new Screen: " << screen; + d->currentScreen = screen; +} + + +void GroupManagerPrivate::checkScreenChange() +{ + //kDebug(); + foreach (const TaskPtr &task, geometryTasks) { + if (!task->isOnScreen(currentScreen) && !task->demandsAttention()) { + q->remove(task); + } else { + q->add(task); + } + } + geometryTasks.clear(); +} + + +void GroupManager::reconnect() +{ + kDebug(); + disconnect(TaskManager::self(), SIGNAL(desktopChanged(int)), + this, SLOT(currentDesktopChanged(int))); + disconnect(TaskManager::self(), SIGNAL(windowChanged(TaskPtr,::TaskManager::TaskChanges)), + this, SLOT(taskChanged(TaskPtr,::TaskManager::TaskChanges))); + + if (d->showOnlyCurrentDesktop || d->showOnlyMinimized || d->showOnlyCurrentScreen) { + // listen to the relevant task manager signals + if (d->showOnlyCurrentDesktop) { + connect(TaskManager::TaskManager::self(), SIGNAL(desktopChanged(int)), + this, SLOT(currentDesktopChanged(int))); + } + + connect(TaskManager::self(), SIGNAL(windowChanged(TaskPtr,::TaskManager::TaskChanges)), + this, SLOT(taskChanged(TaskPtr,::TaskManager::TaskChanges))); + } + + if (d->showOnlyCurrentScreen) { + TaskManager::TaskManager::self()->trackGeometry(true); + } else { + TaskManager::TaskManager::self()->trackGeometry(false); + } + + d->reloadTasks(); +} + + +bool GroupManager::onlyGroupWhenFull() const +{ + return d->onlyGroupWhenFull; +} + +void GroupManager::setOnlyGroupWhenFull(bool state) +{ + kDebug() << state; + d->onlyGroupWhenFull = state; + + if (state) { + connect(d->rootGroup, SIGNAL(itemAdded(AbstractItemPtr)), this, SLOT(checkIfFull())); + connect(d->rootGroup, SIGNAL(itemRemoved(AbstractItemPtr)), this, SLOT(checkIfFull())); + } else { + disconnect(d->rootGroup, SIGNAL(itemAdded(AbstractItemPtr)), this, SLOT(checkIfFull())); + disconnect(d->rootGroup, SIGNAL(itemRemoved(AbstractItemPtr)), this, SLOT(checkIfFull())); + } +} + +void GroupManager::setFullLimit(int limit) +{ + kDebug() << limit; + d->groupIsFullLimit = limit; + if (!onlyGroupWhenFull()) { + return; + } + d->checkIfFull(); +} + +void GroupManagerPrivate::checkIfFull() +{ + kDebug(); + if (!q->onlyGroupWhenFull()) { + return; + } + if (groupingStrategy != GroupManager::ProgramGrouping) { + return; + } + if (itemList.size() >= groupIsFullLimit) { + //kDebug() << "group is full, setting program grouping"; + q->setGroupingStrategy(GroupManager::ProgramGrouping); + } else { + //kDebug() << "group is not full"; + q->setGroupingStrategy(GroupManager::NoGrouping); + //let the visualization thing we still use the programGrouping + groupingStrategy = GroupManager::ProgramGrouping; + } +} + +bool GroupManager::showOnlyCurrentScreen() const +{ + return d->showOnlyCurrentScreen; +} + +void GroupManager::setShowOnlyCurrentScreen(bool showOnlyCurrentScreen) +{ + d->showOnlyCurrentScreen = showOnlyCurrentScreen; +} + +bool GroupManager::showOnlyCurrentDesktop() const +{ + return d->showOnlyCurrentDesktop; +} + +void GroupManager::setShowOnlyCurrentDesktop(bool showOnlyCurrentDesktop) +{ + d->showOnlyCurrentDesktop = showOnlyCurrentDesktop; +} + +bool GroupManager::showOnlyMinimized() const +{ + return d->showOnlyMinimized; +} + +void GroupManager::setShowOnlyMinimized(bool showOnlyMinimized) +{ + d->showOnlyMinimized = showOnlyMinimized; +} + +GroupManager::TaskSortingStrategy GroupManager::sortingStrategy() const +{ + return d->sortingStrategy; +} + +AbstractSortingStrategy* GroupManager::taskSorter() const +{ + return d->abstractSortingStrategy; +} + +void GroupManager::setSortingStrategy(TaskSortingStrategy sortOrder) +{ + kDebug() << sortOrder; + + if (d->abstractSortingStrategy) { + if (d->abstractSortingStrategy->type() == sortOrder){ + return; + } else { + d->abstractSortingStrategy->deleteLater(); + } + } + + switch (sortOrder) { + case NoSorting: //manual and no grouping result both in non automatic grouping + d->abstractSortingStrategy = 0; + break; + case ManualSorting: + d->abstractSortingStrategy = new ManualSortingStrategy(this); + d->abstractSortingStrategy->handleGroup(d->rootGroup); + break; + + case AlphaSorting: + d->abstractSortingStrategy = new AlphaSortingStrategy(this); + d->abstractSortingStrategy->handleGroup(d->rootGroup); + break; + + case DesktopSorting: + kDebug() << "Strategy not implemented"; + //d->abstractSortingStrategy = new DesktopSortingStrategy(this); + break; + + default: + kDebug() << "Invalid Strategy"; + d->abstractSortingStrategy = 0; + } + d->sortingStrategy = sortOrder; + d->reloadTasks(); +} + +GroupManager::TaskGroupingStrategy GroupManager::groupingStrategy() const +{ + return d->groupingStrategy; +} + +AbstractGroupingStrategy* GroupManager::taskGrouper() const +{ + return d->abstractGroupingStrategy; +} + +void GroupManager::setGroupingStrategy(TaskGroupingStrategy strategy) +{ + kDebug() << strategy; + + if (d->abstractGroupingStrategy) { + if (d->abstractGroupingStrategy->type() == strategy){ + return; + } else { + d->abstractGroupingStrategy->deleteLater(); + } + } + + switch (strategy) { + case NoGrouping: + d->abstractGroupingStrategy = 0; + break; + case ManualGrouping: + d->abstractGroupingStrategy = new ManualGroupingStrategy(this); + break; + + case ProgramGrouping: + d->abstractGroupingStrategy = new ProgramGroupingStrategy(this); + break; + + default: + kDebug() << "Strategy not implemented"; + d->abstractGroupingStrategy = 0; + } + d->groupingStrategy = strategy; + d->reloadTasks(); +} + + +} // TaskManager namespace + +#include "groupmanager.moc" + diff --git a/taskmanager/groupmanager.h b/taskmanager/groupmanager.h new file mode 100644 index 000000000..7a5e116f7 --- /dev/null +++ b/taskmanager/groupmanager.h @@ -0,0 +1,153 @@ +/***************************************************************** + +Copyright 2008 Christian Mollekopf + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************/ + +#ifndef GROUPMANAGER_H +#define GROUPMANAGER_H + +#include + +#include +#include +#include +#include + +namespace TaskManager +{ + +class AbstractSortingStrategy; +class AbstractGroupingStrategy; +class GroupManagerPrivate; + +/** + * Manages the grouping stuff. It doesn't know anything about grouping and sorting itself, this is done in the grouping and sorting strategies. + */ +class TASKMANAGER_EXPORT GroupManager: public QObject +{ + +Q_OBJECT +public: + GroupManager(QObject *parent); + ~GroupManager(); + + /** + * Returns a group which contains all items and subgroups. + * Visualizations should be based on this. + */ + GroupPtr rootGroup() const; + + /** + * Strategy used to Group new items + */ + enum TaskGroupingStrategy + { + NoGrouping = 0, + ManualGrouping = 1, //Allow manual grouping + ProgramGrouping = 2 //Group automatically same programs + }; + + TaskGroupingStrategy groupingStrategy() const; + void setGroupingStrategy(TaskGroupingStrategy); + AbstractGroupingStrategy* taskGrouper() const; + + + /** + * How the task are ordered + */ + enum TaskSortingStrategy + { + NoSorting = 0, + ManualSorting = 1, + AlphaSorting = 2, + DesktopSorting = 3 + }; + + TaskSortingStrategy sortingStrategy() const; + void setSortingStrategy(TaskSortingStrategy); + AbstractSortingStrategy* taskSorter() const; + + bool showOnlyCurrentScreen() const; + void setShowOnlyCurrentScreen(bool); + + bool showOnlyCurrentDesktop() const; + void setShowOnlyCurrentDesktop(bool); + + bool showOnlyMinimized() const; + void setShowOnlyMinimized(bool); + + bool onlyGroupWhenFull() const; + /** + * Only apply the grouping startegy when the taskbar is full according to + * setFullLimit(int). This is currently limited to ProgramGrouping. + */ + void setOnlyGroupWhenFull(bool state); + /** + * Set the limit when the taskbar is considered as full + */ + void setFullLimit(int limit); + + /** + * Functions to call if the user wants to do something manually, the strategy allows or refuses the request + */ + bool manualGroupingRequest(AbstractGroupableItem* taskItem, TaskGroup* groupItem); + bool manualGroupingRequest(ItemList items); + + bool manualSortingRequest(AbstractGroupableItem* taskItem, int newIndex); + + /** + * The Visualization is responsible to update the screen number the visualization is currently on. + */ + void setScreen(int screen); + +Q_SIGNALS: + /** Signal that the rootGroup has to be reloaded in the visualization */ + void reload(); + /** Signal that the item is no longer available */ + void itemRemoved(AbstractGroupableItem*); + +public Q_SLOTS: + /** + * Slots for newly added tasks from TaskManager + */ + bool add(TaskPtr); + void remove(TaskPtr); + + void add(StartupPtr); + void remove(StartupPtr); + + /** + * listen to the relevant signals of taskmanager + */ + void reconnect(); + +private: + Q_PRIVATE_SLOT(d, void currentDesktopChanged(int)) + Q_PRIVATE_SLOT(d, void taskChanged(TaskPtr, ::TaskManager::TaskChanges)) + Q_PRIVATE_SLOT(d, void checkScreenChange()) + Q_PRIVATE_SLOT(d, void itemDestroyed()) + Q_PRIVATE_SLOT(d, void checkIfFull()) + + friend class GroupManagerPrivate; + GroupManagerPrivate * const d; +}; +} +#endif diff --git a/taskmanager/startup.cpp b/taskmanager/startup.cpp new file mode 100644 index 000000000..acf1ff223 --- /dev/null +++ b/taskmanager/startup.cpp @@ -0,0 +1,101 @@ +/***************************************************************** + +Copyright (c) 2000-2001 Matthias Elter +Copyright (c) 2001 Richard Moore + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************/ + +// Own +#include "startup.h" + +// Qt +#include + +#include "taskmanager.h" + +namespace TaskManager +{ + +class Startup::Private +{ +public: + Private(const KStartupInfoId& id, const KStartupInfoData& data) + : id(id), data(data) + { + } + + KStartupInfoId id; + KStartupInfoData data; + QSet windowMatches; +}; + +Startup::Startup(const KStartupInfoId& id, const KStartupInfoData& data, + QObject * parent, const char *name) + : QObject(parent), + d(new Private(id, data)) +{ + setObjectName( name ); +} + +Startup::~Startup() +{ + delete d; +} + +QString Startup::text() const +{ + return d->data.findName(); +} + +QString Startup::bin() const +{ + return d->data.bin(); +} + +QString Startup::icon() const +{ + return d->data.findIcon(); +} + +void Startup::update(const KStartupInfoData& data) +{ + d->data.update(data); + emit changed(); +} + +KStartupInfoId Startup::id() const +{ + return d->id; +} + +void Startup::addWindowMatch(WId window) +{ + d->windowMatches.insert(window); +} + +bool Startup::matchesWindow(WId window) const +{ + return d->windowMatches.contains(window); +} + +} // TaskManager namespace + + +#include "startup.moc" diff --git a/taskmanager/startup.h b/taskmanager/startup.h new file mode 100644 index 000000000..a132f90af --- /dev/null +++ b/taskmanager/startup.h @@ -0,0 +1,95 @@ +/***************************************************************** + +Copyright (c) 2000-2001 Matthias Elter +Copyright (c) 2001 Richard Moore + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************/ + +#ifndef STARTUP_H +#define STARTUP_H + +// Qt +#include + +// KDE +#include +#include + +#include + +namespace TaskManager +{ + +class Startup; +typedef KSharedPtr StartupPtr; +typedef QVector StartupList; + +/** + * Represents a task which is in the process of starting. + * + * @see TaskManager + */ +class TASKMANAGER_EXPORT Startup: public QObject, public KShared +{ + Q_OBJECT + Q_PROPERTY(QString text READ text) + Q_PROPERTY(QString bin READ bin) + Q_PROPERTY(QString icon READ icon) + +public: + Startup(const KStartupInfoId& id, const KStartupInfoData& data, QObject * parent, + const char *name = 0); + virtual ~Startup(); + + /** + * The name of the starting task (if known). + */ + QString text() const; + + /** + * The name of the executable of the starting task. + */ + QString bin() const; + + /** + * The name of the icon to be used for the starting task. + */ + QString icon() const; + void update( const KStartupInfoData& data ); + KStartupInfoId id() const; + + void addWindowMatch(WId window); + bool matchesWindow(WId window) const; + +Q_SIGNALS: + /** + * Indicates that this startup has changed in some way. + */ + void changed(); + +private: + class Private; + Private * const d; +}; + +} // TaskManager namespace + + +#endif diff --git a/taskmanager/strategies/alphasortingstrategy.cpp b/taskmanager/strategies/alphasortingstrategy.cpp new file mode 100644 index 000000000..d71214fe2 --- /dev/null +++ b/taskmanager/strategies/alphasortingstrategy.cpp @@ -0,0 +1,95 @@ +/***************************************************************** + +Copyright 2008 Christian Mollekopf + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************/ + +#include "alphasortingstrategy.h" + +#include +#include +#include +#include + +#include + +#include "taskitem.h" +#include "taskgroup.h" +#include "taskmanager.h" + + +namespace TaskManager +{ + +AlphaSortingStrategy::AlphaSortingStrategy(QObject *parent) + :AbstractSortingStrategy(parent) +{ + setType(GroupManager::AlphaSorting); +} + +// used in sortItems +bool lessThan(const QString &s1, const QString &s2) +{ + if (s1.localeAwareCompare(s2) < 0) { + return true; + } + return false; +} + +void AlphaSortingStrategy::sortItems(ItemList &items) +{ + kDebug(); + QMap map; + + foreach (AbstractGroupableItem *groupable, items) { + if (groupable->isGroupItem()) { + TaskGroup *group = qobject_cast(groupable); + if (group) { + map.insertMulti(group->name(), group); + } + } else { + TaskItem *item = qobject_cast(groupable); + if (!item) { + kDebug() << "Wrong object type"; + continue; + } + + if (!item->task()) { + kDebug() << "Null Pointer"; + continue; + } + + //sort by programname not windowname + //kDebug() << "inserting multi item" << item->task()->classClass(); + map.insertMulti(item->task()->classClass(), item); + } + } + + items.clear(); + foreach (AbstractGroupableItem *item, map) { + //kDebug() << item->name(); + items.append(item); + } +} + +} //namespace + +#include "alphasortingstrategy.moc" + diff --git a/taskmanager/strategies/alphasortingstrategy.h b/taskmanager/strategies/alphasortingstrategy.h new file mode 100644 index 000000000..b1b17496a --- /dev/null +++ b/taskmanager/strategies/alphasortingstrategy.h @@ -0,0 +1,50 @@ +/***************************************************************** + +Copyright 2008 Christian Mollekopf + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************/ + +#ifndef ALPHASORTINGSTRATEGY_H +#define ALPHASORTINGSTRATEGY_H + +#include + +#include + +namespace TaskManager +{ + +/** Sorts the tasks alphabetically by programname found in Task::classClass()*/ +class AlphaSortingStrategy : public AbstractSortingStrategy +{ + Q_OBJECT +public: + AlphaSortingStrategy(QObject *parent); + +private: + /** Sorts list of items according to strategy*/ + void sortItems(ItemList&); +}; + +typedef QHash itemHashTable; +typedef QHash desktopHashTable; + +} // TaskManager namespace +#endif diff --git a/taskmanager/strategies/manualgroupingstrategy.cpp b/taskmanager/strategies/manualgroupingstrategy.cpp new file mode 100644 index 000000000..df8bc32af --- /dev/null +++ b/taskmanager/strategies/manualgroupingstrategy.cpp @@ -0,0 +1,534 @@ +/***************************************************************** + +Copyright 2008 Christian Mollekopf + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************/ + +#include "manualgroupingstrategy.h" + +#include + +#include +#include + +#include "abstractgroupingstrategy.h" +#include "groupmanager.h" +#include "taskmanager.h" + + +namespace TaskManager +{ + +class ManualGroupingStrategy::Private +{ +public: + Private() + : currentTemplate(0), + editableGroupProperties(AbstractGroupingStrategy::All), + tempItem(0), + tempGroup(0), + oldDesktop(TaskManager::self()->currentDesktop()) + { + } + + GroupManager *groupManager; + QHash templateTrees; + TaskGroupTemplate* currentTemplate; + QList protectedGroups; + AbstractGroupingStrategy::EditableGroupProperties editableGroupProperties; + AbstractGroupableItem *tempItem; + TaskGroup *tempGroup; + int oldDesktop; +}; + + + +ManualGroupingStrategy::ManualGroupingStrategy(GroupManager *groupManager) + :AbstractGroupingStrategy(groupManager), + d(new Private) +{ + d->groupManager = groupManager; + setType(GroupManager::ManualGrouping); +} + +ManualGroupingStrategy::~ManualGroupingStrategy() +{ + delete d; +} + +AbstractGroupingStrategy::EditableGroupProperties ManualGroupingStrategy::editableGroupProperties() +{ + return d->editableGroupProperties; +} + +QList ManualGroupingStrategy::strategyActions(QObject *parent, AbstractGroupableItem *item) +{ + QList actionList; + + if (item->isGrouped()) { + QAction *a = new QAction(i18n("Leave Group"), parent); + connect(a, SIGNAL(triggered()), this, SLOT(leaveGroup())); + actionList.append(a); + d->tempItem = item; + } + + if (item->isGroupItem()) { + QAction *a = new QAction(i18n("Remove Group"), parent); + connect(a, SIGNAL(triggered()), this, SLOT(removeGroup())); + actionList.append(a); + d->tempGroup = dynamic_cast(item); + } + + return actionList; +} + +void ManualGroupingStrategy::leaveGroup() +{ + Q_ASSERT(d->tempItem); + if (d->tempItem->isGrouped()) { + d->tempItem->parentGroup()->parentGroup()->add(d->tempItem); + } + d->tempItem = 0; +} + +void ManualGroupingStrategy::removeGroup() +{ + Q_ASSERT(d->tempGroup); + if (d->tempGroup->parentGroup()) { + foreach (AbstractGroupableItem *item, d->tempGroup->members()) { + d->tempGroup->parentGroup()->add(item); + } + //Group gets automatically closed on empty signal + } + d->tempGroup = 0; +} + +void ManualGroupingStrategy::unprotectGroup(TaskGroup *group) +{ + kDebug() << group->name() << d->protectedGroups.count(group); + d->protectedGroups.removeOne(group); + if (group->members().isEmpty()) { + closeGroup(group);//check if group is needed anymore + } +} + +void ManualGroupingStrategy::protectGroup(TaskGroup *group) +{ + kDebug() << group->name(); + d->protectedGroups.append(group); +} + +//Check if the item was previously manually grouped +void ManualGroupingStrategy::handleItem(AbstractItemPtr item) +{ + kDebug(); + if (d->currentTemplate) { //TODO this won't work over sessions because the task is identified by the pointer (maybe the name without the current status would work), one way would be to store the items per name if the session is closed and load them per name on startup but use the pointer otherwise because of changing names of browsers etc + TaskGroupTemplate *templateGroup = d->currentTemplate; + kDebug() << templateGroup->name(); + if (templateGroup->hasMember(item)) { + kDebug() << "item found in template tree"; + while(!templateGroup->hasDirectMember(item)) {//Create tree of groups if not already existing + kDebug() << "Creating group tree"; + TaskGroupTemplate *oldTemplateGroup = templateGroup; + AbstractGroupableItem *templateItem = templateGroup->directMember(item); + if (templateItem->isGroupItem()) { + templateGroup = dynamic_cast(templateItem); + } else { + kDebug() << "Error no template Found"; + } + if (templateGroup->group()) { + oldTemplateGroup->group()->add(templateGroup->group()); //add group to parent Group + } else { + //kDebug(); + d->groupManager->rootGroup()->add(item); + return; + } + } + + kDebug() << "Item added to group: " << templateGroup->name(); + templateGroup->group()->add(item); + templateGroup->remove(item); + } else { + kDebug() << "Item not in templates"; + d->groupManager->rootGroup()->add(item); + } + } else { + d->groupManager->rootGroup()->add(item); + } +} + +TaskGroupTemplate *ManualGroupingStrategy::createDuplication(TaskGroup *group) +{ + TaskGroupTemplate *templateGroup = new TaskGroupTemplate(this, group); + return templateGroup; +} + + +void ManualGroupingStrategy::desktopChanged(int newDesktop) +{ + kDebug() << "old: " << d->oldDesktop << "new: " << newDesktop; + if (d->oldDesktop == newDesktop) { + return; + } + + //Store the group under the current Desktop + if (d->currentTemplate) { + d->currentTemplate->clear(); + } + kDebug(); + TaskGroupTemplate *group = createDuplication(d->groupManager->rootGroup()); + d->templateTrees.insert(d->oldDesktop, group); + if (d->templateTrees.contains(newDesktop)) { + kDebug() << "Template found"; + d->currentTemplate = d->templateTrees.value(newDesktop); + connect (d->currentTemplate, SIGNAL(destroyed()), this, SLOT(resetCurrentTemplate())); + } else { + d->currentTemplate = 0; + } + d->oldDesktop = newDesktop; +} + + +//This function makes sure that if the rootGroup template already got deleted nobody tries to access it again +void ManualGroupingStrategy::resetCurrentTemplate() +{ + kDebug(); + d->currentTemplate = 0; +} + +//The group was moved to another desktop, we have to move it to the rootTree of newDesk +void ManualGroupingStrategy::groupChangedDesktop(int newDesktop) +{ + kDebug(); + TaskGroup *group = qobject_cast(sender()); + if (!group) { + return; + } + if (newDesktop && (newDesktop != d->oldDesktop)) { + if (group->parentGroup()) { + group->parentGroup()->remove(group); + } + } + TaskGroupTemplate *templateGroup; +if (newDesktop) { + if (d->templateTrees.contains(newDesktop)) { + kDebug() << "Template found"; + templateGroup = d->templateTrees.value(newDesktop); + } else { + kDebug() << "No Template found"; + templateGroup = new TaskGroupTemplate(this, 0); + templateGroup->setGroup(d->groupManager->rootGroup()); + d->templateTrees.insert(newDesktop, templateGroup); + } + //Add group to all existing desktops +} else { + for (int i = 1; i <= TaskManager::self()->numberOfDesktops(); i++) { + if (d->templateTrees.contains(newDesktop)) { + kDebug() << "Template found"; + templateGroup = d->templateTrees.value(newDesktop); + if (templateGroup->hasMember(group)) { + continue; + } + } else { + kDebug() << "No Template found"; + templateGroup = new TaskGroupTemplate(this, 0); + templateGroup->setGroup(d->groupManager->rootGroup()); + d->templateTrees.insert(newDesktop, templateGroup); + } + templateGroup->add(createDuplication(group)); + } +} + +} + +bool ManualGroupingStrategy::groupItems(ItemList items) +{ + kDebug(); + TaskGroup *group = createGroup(items); + connect(group, SIGNAL(movedToDesktop(int)), this, SLOT(groupChangedDesktop(int))); + setName(nameSuggestions(group).first(), group); + setColor(colorSuggestions(group).first(), group); + setIcon(iconSuggestions(group).first(), group); + return true; +} + +void ManualGroupingStrategy::closeGroup(TaskGroup *group) +{ + kDebug(); + if (!d->protectedGroups.contains(group)) { + AbstractGroupingStrategy::closeGroup(group); + } else if (group->parentGroup()) { + group->parentGroup()->remove(group); + kDebug() << "Group protected"; + } +} + +class TaskGroupTemplate::Private +{ +public: + Private() + : group(0), + parentGroup(0), + groupingStrategy(0) + { + } + + ItemList members; + QString name; + QColor color; + QIcon icon; + TaskGroup *group; + TaskGroupTemplate *parentGroup; + ManualGroupingStrategy *groupingStrategy; +}; + + +TaskGroupTemplate::TaskGroupTemplate(ManualGroupingStrategy *parent, TaskGroup *group) +: AbstractGroupableItem(parent), + d(new Private) +{ + connect(this, SIGNAL(unprotectGroup(TaskGroup *)), parent, SLOT(unprotectGroup(TaskGroup *))); + connect(this, SIGNAL(protectGroup(TaskGroup *)), parent, SLOT(protectGroup(TaskGroup *))); + if (group) { + d->name = group->name(); + d->color = group->color(); + d->icon = group->icon(); + setGroup(group); + foreach (AbstractGroupableItem *item, group->members()) { + //We don't use TaskGroup::add because this would inform the tasks about the change of the group + //and we use the taskgroup just as a temporary container + if (item->isGroupItem()) { + kDebug() << "GroupItem Duplication"; + TaskGroupTemplate *createdDuplication = new TaskGroupTemplate(parent, dynamic_cast(item)); + add(createdDuplication); + } else { + add(item); + } + } + } + kDebug() << "TemplateGroup Created: Name: " << d->name << "Color: " << d->color; +} + +TaskGroupTemplate::~TaskGroupTemplate() +{ + emit unprotectGroup(group()); + emit destroyed(this); + //clear(); + kDebug() << name(); + delete d; +} + +TaskGroup *TaskGroupTemplate::group() +{ + return d->group; +} + +void TaskGroupTemplate::setGroup(TaskGroup *group) +{ + if (d->group) { + emit unprotectGroup(group); + } + if (group) { + emit protectGroup(group); + } + d->group = group; +} + +ItemList &TaskGroupTemplate::members() const +{ + return d->members; +} + +QIcon TaskGroupTemplate::icon() const +{ + return d->icon; +} + +QColor TaskGroupTemplate::color() const +{ + return d->color; +} + +QString TaskGroupTemplate::name() const +{ + return d->name; +} + +/** add item to group */ +void TaskGroupTemplate::add(AbstractItemPtr item) +{ + if (d->members.contains(item)) { + return; + } + d->members.append(item); + if (item->isGroupItem()) { + connect(item, SIGNAL(destroyed(AbstractGroupableItem *)), this, SLOT(itemDestroyed(AbstractGroupableItem *))); + (dynamic_cast(item))->setParentGroup(this); + } +} + +/** remove item from group */ +void TaskGroupTemplate::remove(AbstractItemPtr item) +{ + disconnect(item, 0, this, 0); + disconnect(this, 0, item, 0); + d->members.removeAll(item); + if (item->isGroupItem()) { + (dynamic_cast(item))->setParentGroup(0); + } + if (d->members.isEmpty()) { + closeGroup(); + } +} + +/** Removes all tasks and groups from this group */ +void TaskGroupTemplate::clear() +{ + foreach(AbstractGroupableItem *item, d->members) { + Q_ASSERT(item); + if (item->isGroupItem()) { + TaskGroupTemplate* templateGroup = qobject_cast(item); + Q_ASSERT(templateGroup); + templateGroup->clear(); + } else { + remove(item); + } + } +} +/** Reparents all members and closes this group */ +void TaskGroupTemplate::closeGroup() +{ + if (parentGroup()) { + foreach(AbstractGroupableItem *item, d->members) { + Q_ASSERT(item); + remove(item); + parentGroup()->add(item); + } + } else { + foreach(AbstractGroupableItem *item, d->members) { + Q_ASSERT(item); + remove(item); + } + } + deleteLater(); +} + + +TaskGroupTemplate *TaskGroupTemplate::parentGroup() const +{ + return d->parentGroup; +} + +void TaskGroupTemplate::setParentGroup(TaskGroupTemplate *group) +{ + d->parentGroup = group; +} + + +/** only true if item is in this group */ +bool TaskGroupTemplate::hasDirectMember(AbstractItemPtr item) const +{ + return d->members.contains(item); +} + +/** true if item is in this or any sub group */ +bool TaskGroupTemplate::hasMember(AbstractItemPtr item) const +{ + kDebug(); + if (members().contains(item)) { + return true; + } + ItemList::const_iterator iterator = members().constBegin(); + while (iterator != members().constEnd()) { + if ((*iterator)->isGroupItem()) { + if ((dynamic_cast(*iterator))->hasMember(item)) { //look into group + return true; + } + } + ++iterator; + } + return false; + +} + +/** Returns Direct Member group if the passed item is in a subgroup */ +AbstractItemPtr TaskGroupTemplate::directMember(AbstractItemPtr item) const +{ + if (members().contains(item)) { + return item; + } else { + ItemList::const_iterator iterator = members().constBegin(); + while (iterator != members().constEnd()) { + if ((*iterator)->isGroupItem()) { + if ((dynamic_cast(*iterator))->hasMember(item)) { + kDebug() << "item found"; + return (*iterator); + } + } + ++iterator; + } + } + kDebug() << "item not found"; + return AbstractItemPtr(); +} + +TaskGroupTemplate *TaskGroupTemplate::findParentGroup(AbstractItemPtr item) const +{ + if (members().contains(item)) { + return const_cast(this); + } else { + ItemList::const_iterator iterator = members().constBegin(); + while (iterator != members().constEnd()) { + if ((*iterator)->isGroupItem()) { + TaskGroupTemplate *returnedGroup = (dynamic_cast(*iterator))->findParentGroup(item); + if (returnedGroup) { + kDebug() << "item found"; + return returnedGroup; + } + } + ++iterator; + } + } + kDebug() << "item not found"; + return 0; +} + +void TaskGroupTemplate::itemDestroyed(AbstractGroupableItem *item) +{ + if (!item) { + kDebug() << "Error"; + return; + } + kDebug() << d->group->name(); + /** + * The following code is needed in case one creates a group on desktop 1 with a task which is on multiple * * desktops. If this task gets closed on another desktop as last task in the group the empty group is still * stored in the template and therefore all attributes (name, color, ..) stay reserved + */ + d->members.removeAll(item); // we can't use remove because the item was already deleted + disconnect(item, 0, this, 0); + disconnect(this, 0, item, 0); + if (members().isEmpty()) { + closeGroup(); + } +} + +}//namespace + +#include "manualgroupingstrategy.moc" + diff --git a/taskmanager/strategies/manualgroupingstrategy.h b/taskmanager/strategies/manualgroupingstrategy.h new file mode 100644 index 000000000..50c46d716 --- /dev/null +++ b/taskmanager/strategies/manualgroupingstrategy.h @@ -0,0 +1,213 @@ +/***************************************************************** + +Copyright 2008 Christian Mollekopf + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************/ + +#ifndef MANUALGROUPINGSTRATEGY_H +#define MANUALGROUPINGSTRATEGY_H + +#include "abstractgroupingstrategy.h" +#include "taskgroup.h" + +namespace TaskManager +{ + +class ManualGroupingStrategy; +/** + * TaskGroup, a container for tasks and subgroups + */ + +class TaskGroupTemplate : public AbstractGroupableItem +{ + Q_OBJECT +public: + TaskGroupTemplate(ManualGroupingStrategy *parent, TaskGroup *group); + ~TaskGroupTemplate(); + + TaskGroup *group(); + void setGroup(TaskGroup *); + + ItemList &members() const; + QIcon icon() const; + QColor color() const; + QString name() const; + + bool isGroupItem() const { return true; } + + /** only true if item is in this group */ + bool hasDirectMember(AbstractItemPtr item) const; + /** only true if item is in this or any sub group */ + bool hasMember(AbstractItemPtr item) const; + /** Returns Direct Member group if the passed item is in a subgroup */ + AbstractItemPtr directMember(AbstractItemPtr) const; + + TaskGroupTemplate *findParentGroup(AbstractItemPtr item) const; + + TaskGroupTemplate *parentGroup() const; + void setParentGroup(TaskGroupTemplate *); + +Q_SIGNALS: + /** Unprotects group so it can get closed + */ + void unprotectGroup(TaskGroup *); + /** used to inform the group that there is still a desktop with this group so it wont + * be closed when empty + */ + void protectGroup(TaskGroup *); + + void destroyed(AbstractGroupableItem *); + +private Q_SLOTS: + void itemDestroyed(AbstractGroupableItem *); + + +public Q_SLOTS: + /** Needed because we subclass AbstractGroupableItem */ + void toDesktop(int) {} + bool isOnCurrentDesktop() const { return false; } + bool isOnAllDesktops() const { return false; } + int desktop() const {return 0; } + + void setShaded(bool) {} + void toggleShaded() {} + bool isShaded() const {return false; } + + void setMaximized(bool) {} + void toggleMaximized() {} + bool isMaximized() const {return false; } + + void setMinimized(bool) {} + void toggleMinimized() {} + bool isMinimized() const { return false; } + + void setFullScreen(bool) {} + void toggleFullScreen() {} + bool isFullScreen() const { return false; } + + void setKeptBelowOthers(bool) {} + void toggleKeptBelowOthers() {} + bool isKeptBelowOthers() const { return false; } + + void setAlwaysOnTop(bool) {} + void toggleAlwaysOnTop() {} + bool isAlwaysOnTop() const { return false; } + + bool isActionSupported(NET::Action) const { return false; } + + /** close all members of this group */ + void close() {} + + /** returns true if at least one member is active */ + bool isActive() const { return false; } + /** returns true if at least one member is demands attention */ + bool demandsAttention() const { return false; } + + /** add item to group */ + void add(AbstractItemPtr); + + /** remove item from group */ + void remove(AbstractItemPtr); + + /** Removes all tasks and groups from this group */ + void clear(); + + /** remove this group, passes all members to grouping strategy*/ + void closeGroup(); + +private: + class Private; + Private * const d; +}; + + + + +class GroupManager; +/** + * Remembers manually grouped tasks + * To do this it keeps an exact copy of the rootGroup and all subgroups + * for each desktop/screen + */ +class ManualGroupingStrategy: public AbstractGroupingStrategy +{ + Q_OBJECT +public: + ManualGroupingStrategy(GroupManager *groupingStrategy); + ~ManualGroupingStrategy(); + + /** looks up if this item has been grouped before and groups it accordingly. + *otherwise the item goes to the rootGroup + */ + void handleItem(AbstractItemPtr); + /** Should be called if the user wants to manually add an item to a group */ + //bool addItemToGroup(AbstractGroupableItem*, TaskGroup*); + /** Should be called if the user wants to group items manually */ + bool groupItems(ItemList items); + + /** Returns list of actions that a task can do in this groupingStrategy + * fore example: remove this Task from this group + */ + QList strategyActions(QObject *parent, AbstractGroupableItem *item); + + EditableGroupProperties editableGroupProperties(); + + void desktopChanged(int newDesktop); + +private slots: + + /** Actions which the strategy offers*/ + /** sender item leaves group*/ + void leaveGroup(); + /** Removes all items from the sender group and adds to the parent Group*/ + void removeGroup(); + + + void groupChangedDesktop(int newDesk); + /** Protects group from being closed, because the tasks in the group are just temporarily + * not available (not on the desktop,...). Every TaskGroupTemplate calls this so the group is + * is only closed if it isn't present on any desktop. + */ + void protectGroup(TaskGroup *group); + /** Unprotects group so it can get closed + */ + void unprotectGroup(TaskGroup *group); + /** This function makes sure that if the rootGroup template already got deleted nobody tries to access it again*/ + void resetCurrentTemplate(); + +protected: + void closeGroup(TaskGroup*); + +private: + bool manualGrouping(TaskItem* taskItem, TaskGroup* groupItem); + + /** Create a duplication of a group with all subgroups TaskItems arent duplicated */ + TaskGroupTemplate *createDuplication(TaskGroup *group); + + class Private; + Private * const d; +}; + + +} + + + +#endif diff --git a/taskmanager/strategies/manualsortingstrategy.cpp b/taskmanager/strategies/manualsortingstrategy.cpp new file mode 100644 index 000000000..f6b6a8326 --- /dev/null +++ b/taskmanager/strategies/manualsortingstrategy.cpp @@ -0,0 +1,157 @@ +/***************************************************************** + +Copyright 2008 Christian Mollekopf + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************/ + +#include "manualsortingstrategy.h" + +#include "taskitem.h" +#include "taskgroup.h" +#include "taskmanager.h" + +#include +#include + +#include + + +namespace TaskManager +{ + +class ManualSortingStrategy::Private +{ +public: + Private() + { + } + GroupManager *groupingStrategy; + + itemHashTable *managedItems; + desktopHashTable *desktops; + int oldDesktop; +}; + + +ManualSortingStrategy::ManualSortingStrategy(GroupManager *parent) + :AbstractSortingStrategy(parent), + d(new Private) +{ + d->groupingStrategy = parent; + setType(GroupManager::ManualSorting); + + d->desktops = new desktopHashTable(); + //TODO add a screenHashTable + d->oldDesktop = TaskManager::TaskManager::self()->currentDesktop(); + + if (d->groupingStrategy->showOnlyCurrentDesktop()) { + d->desktops->insert(TaskManager::TaskManager::self()->currentDesktop(), new itemHashTable()); + d->managedItems = d->desktops->value(TaskManager::TaskManager::self()->currentDesktop()); + } else { + d->desktops->insert(0,new itemHashTable()); + d->managedItems = d->desktops->value(0); + } +} + +ManualSortingStrategy::~ManualSortingStrategy() +{ + if (d->desktops) { + foreach(itemHashTable *table, *d->desktops) { + if (table) { + delete table; + } + } + delete d->desktops; + } + delete d; +} + +void ManualSortingStrategy::storePositions(TaskGroup *group) +{ + Q_ASSERT(group); + for(int i = 0; i < group->members().size(); i++) { + AbstractGroupableItem *item = group->members().at(i); + Q_ASSERT(item); + if (item->isGroupItem()) { + d->managedItems->insert(item, i); + storePositions(dynamic_cast(item)); + } else { + d->managedItems->insert(item, i); + } + kDebug() << item << i; + } +} + +//Here we should store all infos about the sorting +void ManualSortingStrategy::desktopChanged(int newDesktop) +{ + kDebug() << "Desktop changed" << d->oldDesktop << newDesktop; + //store positions of old desktop + d->managedItems->clear(); + storePositions(d->groupingStrategy->rootGroup()); + d->desktops->insert(d->oldDesktop, d->managedItems); + + //load positions of new desktop + if (d->desktops->contains(newDesktop)) { + d->managedItems = d->desktops->value(newDesktop); + } else { + d->managedItems = new itemHashTable(); + } + + d->oldDesktop = newDesktop; +} + +void ManualSortingStrategy::sortItems(ItemList &items) +{ + kDebug(); + + QMap map; + int i = 1000; + foreach (AbstractGroupableItem *item, items) { + if (d->managedItems->contains(item)) { + map.insertMulti(d->managedItems->value(item), item); + } else {//make sure unkwown items are appended + kDebug() << "item not found in managedItems"; + map.insertMulti(i, item); + i++; + } + } + items.clear(); + items = map.values(); +} + +//since we have no way of knowing about a desktop change before it happens we have to track every single change.... +void ManualSortingStrategy::handleItem(AbstractItemPtr item) +{ + if (d->managedItems->contains(item)) { + if (item->isGroupItem()) { + handleGroup(qobject_cast(item)); + } + check(item); + } else { + Q_ASSERT(item->parentGroup()); + d->managedItems->insert(item, item->parentGroup()->members().indexOf(item)); + } +} + +} //namespace + +#include "manualsortingstrategy.moc" + diff --git a/taskmanager/strategies/manualsortingstrategy.h b/taskmanager/strategies/manualsortingstrategy.h new file mode 100644 index 000000000..8b3647388 --- /dev/null +++ b/taskmanager/strategies/manualsortingstrategy.h @@ -0,0 +1,65 @@ +/***************************************************************** + +Copyright 2008 Christian Mollekopf + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************/ + +#ifndef MANUALSORTINGSTRATEGY_H +#define MANUALSORTINGSTRATEGY_H + +#include "abstractsortingstrategy.h" + +namespace TaskManager +{ + +/** +* Manual Sorting +* If showAllDesktops is enabled the position of the tasks logically changes on all desktops +* If showAllDesktops is disabled the position only changes per virtual desktop even +* if the task is on all desktops +*/ + +class ManualSortingStrategy : public AbstractSortingStrategy +{ + Q_OBJECT +public: + ManualSortingStrategy(GroupManager *parent); + ~ManualSortingStrategy(); + + /** DesktopChanges, time to backup any needed data */ + void desktopChanged(int newDesktop); + +protected Q_SLOTS: + /** Handles a new item*/ + virtual void handleItem(AbstractItemPtr); + +private: + /** Sorts list of items*/ + void sortItems(ItemList&); + + void storePositions(TaskGroup *group); + + class Private; + Private * const d; +}; + + +} // TaskManager namespace +#endif diff --git a/taskmanager/strategies/programgroupingstrategy.cpp b/taskmanager/strategies/programgroupingstrategy.cpp new file mode 100644 index 000000000..2f58ca581 --- /dev/null +++ b/taskmanager/strategies/programgroupingstrategy.cpp @@ -0,0 +1,190 @@ +/***************************************************************** + +Copyright 2008 Christian Mollekopf + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************/ + +#include "programgroupingstrategy.h" + +#include + +#include +#include + +#include "abstractgroupingstrategy.h" +#include "groupmanager.h" + +namespace TaskManager +{ + +class ProgramGroupingStrategy::Private +{ +public: + Private() + :editableGroupProperties(AbstractGroupingStrategy::None) + { + } + GroupManager *groupManager; + AbstractGroupingStrategy::EditableGroupProperties editableGroupProperties; + AbstractGroupableItem *tempItem; + QStringList blackList; //Programs in this list should not be grouped +}; + + +ProgramGroupingStrategy::ProgramGroupingStrategy(GroupManager *groupManager) + :AbstractGroupingStrategy(groupManager), + d(new Private) +{ + d->groupManager = groupManager; + setType(GroupManager::ProgramGrouping); +} + +ProgramGroupingStrategy::~ProgramGroupingStrategy() +{ + delete d; +} + +QList ProgramGroupingStrategy::strategyActions(QObject *parent, AbstractGroupableItem *item) +{ + QAction *a = new QAction(parent); + QString name = className(item); + if (d->blackList.contains(name)) { + a->setText(i18n("Allow This Program to Be Grouped")); + } else { + a->setText(i18n("Do Not Allow This Program to Be Grouped")); + } + connect(a, SIGNAL(triggered()), this, SLOT(toggleGrouping())); + + QList actionList; + actionList.append(a); + d->tempItem = item; + return actionList; +} + +QString ProgramGroupingStrategy::className(AbstractGroupableItem *item) +{ + QString name; + if (item->isGroupItem()) { //maybe add the condition that the subgroup was created by programGrouping + TaskGroup *group = qobject_cast(item); + TaskItem *task = qobject_cast(group->members().first()); //There are only TaskItems in programGrouping groups + return task->task()->classClass(); + } + + return (qobject_cast(item))->task()->classClass(); +} + +void ProgramGroupingStrategy::toggleGrouping() +{ + QString name = className(d->tempItem); + + if (d->blackList.contains(name)) { + d->blackList.removeAll(name); + if (d->tempItem->isGroupItem()) { + foreach (AbstractGroupableItem *item, (qobject_cast(d->tempItem))->members()) { + handleItem(item); + } + } else { + handleItem(d->tempItem); + } + } else { + d->blackList.append(name); + if (d->tempItem->isGroupItem()) { + closeGroup(qobject_cast(d->tempItem)); + } else { + d->groupManager->rootGroup()->add(d->tempItem); + } + } + d->tempItem = 0; +} + +void ProgramGroupingStrategy::handleItem(AbstractItemPtr item) +{ + if (item->isGroupItem()) { + d->groupManager->rootGroup()->add(item); + return; + } else if (d->blackList.contains((qobject_cast(item))->task()->classClass())) { + d->groupManager->rootGroup()->add(item); + return; + } + + TaskItem *task = dynamic_cast(item); + if (task && !programGrouping(task, d->groupManager->rootGroup())) { + kDebug() << "joined rootGroup "; + d->groupManager->rootGroup()->add(item); + } +} + +bool ProgramGroupingStrategy::programGrouping(TaskItem* taskItem, TaskGroup* groupItem) +{ + kDebug(); + QHash itemMap; + + foreach (AbstractItemPtr item, groupItem->members()) { //search for an existing group + if (item->isGroupItem()) { //maybe add the condition that the subgroup was created by programGrouping + if (programGrouping(taskItem, static_cast(item))) { + kDebug() << "joined subGroup"; + return true; + } + } else { + TaskItem *task = static_cast(item); + if (task->task()) { //omit startup tasks + QString name = task->task()->classClass(); + itemMap.insertMulti(name,item); + } + } + } + + if (!itemMap.values().contains(taskItem)) { + itemMap.insertMulti(taskItem->task()->classClass(), taskItem); + } + + QString name = taskItem->task()->classClass(); + if (itemMap.count(name) >= groupItem->members().count()) { //join this group + kDebug() << "joined this Group"; + groupItem->add(taskItem); + return true; + } else if (itemMap.count(name) >= 2) { //create new subgroup with at least 2 other task + kDebug() << "create Group"; + QIcon icon = taskItem->task()->icon(); + QList list(itemMap.values(name)); + TaskGroup* group = createGroup(list); + group->setName(name); + group->setColor(Qt::red); + group->setIcon(icon); + return true; + } + return false; +} + +void ProgramGroupingStrategy::checkGroup() +{ + TaskGroup *group = qobject_cast(sender()); + if (!group) { + return; + } + if (group->members().size() <= 1) { + closeGroup(group); + } +} + +}//namespace + +#include "programgroupingstrategy.moc" + diff --git a/taskmanager/strategies/programgroupingstrategy.h b/taskmanager/strategies/programgroupingstrategy.h new file mode 100644 index 000000000..f6ae573bf --- /dev/null +++ b/taskmanager/strategies/programgroupingstrategy.h @@ -0,0 +1,77 @@ +/***************************************************************** + +Copyright 2008 Christian Mollekopf + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************/ + +#ifndef PROGRAMGROUPINGSTRATEGY_H +#define PROGRAMGROUPINGSTRATEGY_H + +#include "abstractgroupingstrategy.h" +#include "taskgroup.h" + +namespace TaskManager +{ + +class GroupManager; + +/** + * Groups tasks of the same program + */ +class ProgramGroupingStrategy: public AbstractGroupingStrategy +{ + Q_OBJECT +public: + ProgramGroupingStrategy(GroupManager *groupManager); + ~ProgramGroupingStrategy(); + /** Tasks are passed to this function to be grouped by this strategy + */ + void handleItem(AbstractItemPtr); + + /** Returns list of actions that a task can do in this groupingStrategy + * fore example: start/stop group tasks of this program + */ + QList strategyActions(QObject *parent, AbstractGroupableItem *item); + + EditableGroupProperties editableGroupProperties(){return None;}; + +protected Q_SLOTS: + /** Checks if the group is still necessary */ + void checkGroup(); +private Q_SLOTS: + /** The program of the sender() of this function is started or stopped being grouped + * by this strategy. This is done by adding the program to d->blackList + */ + void toggleGrouping(); + +private: + QString className(AbstractGroupableItem *item); + bool programGrouping(TaskItem* taskItem, TaskGroup* groupItem); + class Private; + Private * const d; + +}; + + +} + + + +#endif diff --git a/taskmanager/task.cpp b/taskmanager/task.cpp new file mode 100644 index 000000000..60ab6143e --- /dev/null +++ b/taskmanager/task.cpp @@ -0,0 +1,1067 @@ +/***************************************************************** + +Copyright (c) 2000-2001 Matthias Elter +Copyright (c) 2001 Richard Moore + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************/ + +// Own +#include "task.h" + +// Qt +#include +#include +#include +#include + +#ifdef Q_WS_X11 +#include +#endif + +// KDE +#include +#include +#include + +#include "taskmanager.h" +#include "taskmanager_p.h" + +namespace TaskManager +{ + +class Task::Private +{ +public: + Private(WId w) + : active(false), + win(w), + frameId(w), + info(KWindowSystem::windowInfo(w, + NET::WMState | NET::XAWMState | NET::WMDesktop | + NET::WMVisibleName | NET::WMGeometry | NET::WMWindowType, + NET::WM2AllowedActions)), + lastWidth(0), + lastHeight(0), + lastResize(false), + lastIcon(), + thumbSize(0.2), + thumb(), + grab() + { + } + + bool active; + WId win; + WId frameId; + QPixmap pixmap; + KWindowInfo info; + WindowList transients; + WindowList transientsDemandingAttention; + + int lastWidth; + int lastHeight; + bool lastResize; + QPixmap lastIcon; + QIcon icon; + + double thumbSize; + QPixmap thumb; + QPixmap grab; + QRect iconGeometry; + + Pixmap windowPixmap; +}; + +Task::Task(WId w, QObject *parent, const char *name) + : QObject(parent), + d(new Private(w)) +{ + setObjectName( name ); + + // try to load icon via net_wm + d->pixmap = KWindowSystem::icon(d->win, 16, 16, true); + + // try to guess the icon from the classhint + if (d->pixmap.isNull()) + { + KIconLoader::global()->loadIcon(className().toLower(), + KIconLoader::Small, + KIconLoader::Small, + KIconLoader::DefaultState, + QStringList(), 0, true); + } + + // load the icon for X applications + if (d->pixmap.isNull()) + { + d->pixmap = SmallIcon("xorg"); + } + +#ifdef THUMBNAILING_POSSIBLE + d->windowPixmap = 0; + findWindowFrameId(); + + if (KWindowSystem::compositingActive()) + { + updateWindowPixmap(); + } +#endif // THUMBNAILING_POSSIBLE +} + +Task::~Task() +{ +#ifdef THUMBNAILING_POSSIBLE + //be sure we have something to delete + if (d->windowPixmap && QX11Info::display()) + { + XFreePixmap(QX11Info::display(), d->windowPixmap); + } +#endif // THUMBNAILING_POSSIBLE + delete d; +} + +// Task::findWindowFrameId() +// Code was copied from Kompose. +// Copyright (C) 2004 Hans Oischinger +// Permission granted on 2005-04-27. +void Task::findWindowFrameId() +{ +#ifdef THUMBNAILING_POSSIBLE + Window targetWin, parent, root; + Window *children; + uint nchildren; + + targetWin = d->win; + for (;;) + { + if (!XQueryTree(QX11Info::display(), targetWin, &root, + &parent, &children, &nchildren)) + { + break; + } + + if (children) + { + XFree(children); // it's a list, that's deallocated! + } + + if (!parent || parent == root) + { + break; + } + else + { + targetWin = parent; + } + } + + d->frameId = targetWin; +#endif // THUMBNAILING_POSSIBLE +} + +void Task::refreshIcon() +{ + // try to load icon via net_wm + d->pixmap = KWindowSystem::icon(d->win, 16, 16, true); + + // try to guess the icon from the classhint + if(d->pixmap.isNull()) + { + KIconLoader::global()->loadIcon(className().toLower(), + KIconLoader::Small, + KIconLoader::Small, + KIconLoader::DefaultState, + QStringList(), 0, true); + } + + // load the icon for X applications + if (d->pixmap.isNull()) + { + d->pixmap = SmallIcon("xorg"); + } + + d->lastIcon = QPixmap(); + d->icon = QIcon(); + emit changed(IconChanged); +} + +::TaskManager::TaskChanges Task::refresh(unsigned int dirty) +{ + KWindowInfo info = KWindowSystem::windowInfo(d->win, + NET::WMState | NET::XAWMState | NET::WMDesktop | NET::WMVisibleName | NET::WMGeometry | NET::WMWindowType, + NET::WM2AllowedActions); + + TaskChanges changes = TaskUnchanged; + + if (d->info.visibleName() != info.visibleName() || + d->info.visibleNameWithState() != info.visibleNameWithState() || + d->info.name() != info.name()) { + changes |= NameChanged; + } + + d->info = info; + + if (dirty & NET::WMState || dirty & NET::XAWMState) { + changes |= StateChanged; + } + + if (dirty & NET::WMDesktop) { + changes |= DesktopChanged; + } + + if (dirty & NET::WMGeometry) { + changes |= GeometryChanged; + } + + if (dirty & NET::WMWindowType) { + changes |= WindowTypeChanged; + } + + if (dirty & NET::WM2AllowedActions) { + changes |= ActionsChanged; + } + + if (changes != TaskUnchanged) { + emit changed(changes); + } + + return changes; +} + +void Task::setActive(bool a) +{ + d->active = a; + emit changed(StateChanged); + if (a) { + emit activated(); + } else { + emit deactivated(); + } +} + +double Task::thumbnailSize() const { return d->thumbSize; } + + +void Task::setThumbnailSize( double size ) +{ + d->thumbSize = size; +} + +bool Task::hasThumbnail() const +{ + return !d->thumb.isNull(); +} + +QPixmap Task::thumbnail() const +{ + return d->thumb; +} + +bool Task::isMaximized() const +{ + return d->info.valid() && (d->info.state() & NET::Max); +} + +bool Task::isMinimized() const +{ + return d->info.valid() && d->info.isMinimized(); +} + +bool Task::isIconified() const +{ + return d->info.valid() && d->info.isMinimized(); +} + +bool Task::isAlwaysOnTop() const +{ + return d->info.valid() && (d->info.state() & NET::StaysOnTop); +} + +bool Task::isKeptBelowOthers() const +{ + return d->info.valid() && (d->info.state() & NET::KeepBelow); +} + +bool Task::isFullScreen() const +{ + return d->info.valid() && (d->info.state() & NET::FullScreen); +} + +bool Task::isShaded() const +{ + return d->info.valid() && (d->info.state() & NET::Shaded); +} + +bool Task::isOnCurrentDesktop() const +{ + return d->info.valid() && d->info.isOnCurrentDesktop(); +} + +bool Task::isOnAllDesktops() const +{ + return d->info.valid() && d->info.onAllDesktops(); +} + +bool Task::isActive() const +{ + return d->active; +} + +bool Task::isOnTop() const +{ + return TaskManager::self()->isOnTop(this); +} + +bool Task::isModified() const +{ + static QString modStr = QString::fromUtf8("[") + + i18n("modified") + + QString::fromUtf8("]"); + int modStrPos = d->info.visibleName().indexOf(modStr); + + return ( modStrPos != -1 ); +} + +int Task::desktop() const +{ + return d->info.desktop(); +} + +bool Task::demandsAttention() const +{ + return (d->info.valid() && (d->info.state() & NET::DemandsAttention)) || + d->transientsDemandingAttention.count() > 0; +} + +bool Task::isOnScreen( int screen ) const +{ + return TaskManager::isOnScreen( screen, d->win ); +} + +bool Task::showInTaskbar() const +{ + return d->info.state() ^ NET::SkipTaskbar; +} + +bool Task::showInPager() const +{ + return d->info.state() ^ NET::SkipPager; +} + +QRect Task::geometry() const +{ + return d->info.geometry(); +} + +void Task::updateDemandsAttentionState( WId w ) +{ + if (window() != w) + { + // 'w' is a transient for this task + NETWinInfo i( QX11Info::display(), w, QX11Info::appRootWindow(), NET::WMState ); + if(i.state() & NET::DemandsAttention) + { + if (!d->transientsDemandingAttention.contains(w)) + { + d->transientsDemandingAttention.append(w); + } + } + else + { + d->transientsDemandingAttention.removeAll( w ); + } + } +} + +void Task::addTransient( WId w, const NETWinInfo& info ) +{ + d->transients.append(w); + if (info.state() & NET::DemandsAttention) + { + d->transientsDemandingAttention.append(w); + emit changed(TransientsChanged); + } +} + +void Task::removeTransient(WId w) +{ + d->transients.removeAll(w); + d->transientsDemandingAttention.removeAll(w); +} + +bool Task::hasTransient(WId w) const +{ + return d->transients.indexOf(w) != -1; +} + +WId Task::window() const +{ + return d->win; +} + +KWindowInfo Task::info() const +{ + return d->info; +} + +QString Task::visibleName() const +{ + return d->info.visibleName(); +} + +QString Task::visibleNameWithState() const +{ + return d->info.visibleNameWithState(); +} + +QString Task::name() const +{ + return d->info.name(); +} + +QString Task::className() const +{ + XClassHint hint; + if(XGetClassHint(QX11Info::display(), d->win, &hint)) { + QString nh( hint.res_name ); + XFree( hint.res_name ); + XFree( hint.res_class ); + return nh; + } + return QString(); +} + +QString Task::classClass() const +{ + XClassHint hint; + if(XGetClassHint(QX11Info::display(), d->win, &hint)) { + QString ch( hint.res_class ); + XFree( hint.res_name ); + XFree( hint.res_class ); + return ch; + } + return QString(); +} + +QPixmap Task::icon( int width, int height, bool allowResize ) +{ + if ( (width == d->lastWidth) + && (height == d->lastHeight) + && (allowResize == d->lastResize ) + && (!d->lastIcon.isNull()) ) + return d->lastIcon; + + QPixmap newIcon = KWindowSystem::icon( d->win, width, height, allowResize ); + if ( !newIcon.isNull() ) { + d->lastIcon = newIcon; + d->lastWidth = width; + d->lastHeight = height; + d->lastResize = allowResize; + } + + return newIcon; +} + +QIcon Task::icon() +{ + if ( !d->icon.isNull() ) + return d->icon; + + d->icon.addPixmap(KWindowSystem::icon( d->win, KIconLoader::SizeSmall, KIconLoader::SizeSmall, false)); + d->icon.addPixmap(KWindowSystem::icon( d->win, KIconLoader::SizeSmallMedium, KIconLoader::SizeSmallMedium, false)); + d->icon.addPixmap(KWindowSystem::icon( d->win, KIconLoader::SizeMedium, KIconLoader::SizeMedium, false)); + d->icon.addPixmap(KWindowSystem::icon( d->win, KIconLoader::SizeLarge, KIconLoader::SizeLarge, false)); + + return d->icon; +} + + + +WindowList Task::transients() const +{ + return d->transients; +} + +QPixmap Task::pixmap() const +{ + return d->pixmap; +} + +QPixmap Task::bestIcon( int size, bool &isStaticIcon ) +{ + QPixmap pixmap; + isStaticIcon = false; + + switch( size ) { + case KIconLoader::SizeSmall: + { + pixmap = icon( 16, 16, true ); + + // Icon of last resort + if( pixmap.isNull() ) { + pixmap = KIconLoader::global()->loadIcon( "xorg", + KIconLoader::NoGroup, + KIconLoader::SizeSmall ); + isStaticIcon = true; + } + } + break; + case KIconLoader::SizeMedium: + { + // + // Try 34x34 first for KDE 2.1 icons with shadows, if we don't + // get one then try 32x32. + // + pixmap = icon( 34, 34, false ); + + if ( (( pixmap.width() != 34 ) || ( pixmap.height() != 34 )) && + (( pixmap.width() != 32 ) || ( pixmap.height() != 32 )) ) + { + pixmap = icon( 32, 32, true ); + } + + // Icon of last resort + if( pixmap.isNull() ) { + pixmap = KIconLoader::global()->loadIcon( "xorg", + KIconLoader::NoGroup, + KIconLoader::SizeMedium ); + isStaticIcon = true; + } + } + break; + case KIconLoader::SizeLarge: + { + // If there's a 48x48 icon in the hints then use it + pixmap = icon( size, size, false ); + + // If not, try to get one from the classname + if ( pixmap.isNull() || pixmap.width() != size || pixmap.height() != size ) { + pixmap = KIconLoader::global()->loadIcon( className(), + KIconLoader::NoGroup, + size, + KIconLoader::DefaultState, + QStringList(), 0L, + true ); + isStaticIcon = true; + } + + // If we still don't have an icon then scale the one in the hints + if ( pixmap.isNull() || ( pixmap.width() != size ) || ( pixmap.height() != size ) ) { + pixmap = icon( size, size, true ); + isStaticIcon = false; + } + + // Icon of last resort + if( pixmap.isNull() ) { + pixmap = KIconLoader::global()->loadIcon( "xorg", + KIconLoader::NoGroup, + size ); + isStaticIcon = true; + } + } + } + + return pixmap; +} + +bool Task::idMatch( const QString& id1, const QString& id2 ) +{ + if ( id1.isEmpty() || id2.isEmpty() ) + return false; + + if ( id1.contains( id2 ) > 0 ) + return true; + + if ( id2.contains( id1 ) > 0 ) + return true; + + return false; +} + +void Task::move() +{ + bool on_current = d->info.isOnCurrentDesktop(); + + if (!on_current) + { + KWindowSystem::setCurrentDesktop(d->info.desktop()); + KWindowSystem::forceActiveWindow(d->win); + } + + if (d->info.isMinimized()) + { + KWindowSystem::unminimizeWindow(d->win); + } + + QRect geom = d->info.geometry(); + QCursor::setPos(geom.center()); + + NETRootInfo ri(QX11Info::display(), NET::WMMoveResize); + ri.moveResizeRequest(d->win, geom.center().x(), + geom.center().y(), NET::Move); +} + +void Task::resize() +{ + bool on_current = d->info.isOnCurrentDesktop(); + + if (!on_current) + { + KWindowSystem::setCurrentDesktop(d->info.desktop()); + KWindowSystem::forceActiveWindow(d->win); + } + + if (d->info.isMinimized()) + { + KWindowSystem::unminimizeWindow(d->win); + } + + QRect geom = d->info.geometry(); + QCursor::setPos(geom.bottomRight()); + + NETRootInfo ri(QX11Info::display(), NET::WMMoveResize); + ri.moveResizeRequest(d->win, geom.bottomRight().x(), + geom.bottomRight().y(), NET::BottomRight); +} + +void Task::setMaximized(bool maximize) +{ + KWindowInfo info = KWindowSystem::windowInfo(d->win, NET::WMState | NET::XAWMState | NET::WMDesktop); + bool on_current = info.isOnCurrentDesktop(); + + if (!on_current) + { + KWindowSystem::setCurrentDesktop(info.desktop()); + } + + if (info.isMinimized()) + { + KWindowSystem::unminimizeWindow(d->win); + } + + NETWinInfo ni(QX11Info::display(), d->win, QX11Info::appRootWindow(), NET::WMState); + + if (maximize) + { + ni.setState(NET::Max, NET::Max); + } + else + { + ni.setState(0, NET::Max); + } + + if (!on_current) + { + KWindowSystem::forceActiveWindow(d->win); + } +} + +void Task::toggleMaximized() +{ + setMaximized(!isMaximized()); +} + +void Task::restore() +{ + KWindowInfo info = KWindowSystem::windowInfo(d->win, NET::WMState | NET::XAWMState | NET::WMDesktop); + bool on_current = info.isOnCurrentDesktop(); + + if (!on_current) + { + KWindowSystem::setCurrentDesktop(info.desktop()); + } + + if( info.isMinimized()) + { + KWindowSystem::unminimizeWindow(d->win); + } + + NETWinInfo ni(QX11Info::display(), d->win, QX11Info::appRootWindow(), NET::WMState); + ni.setState(0, NET::Max); + + if (!on_current) + { + KWindowSystem::forceActiveWindow( d->win ); + } +} + +void Task::setIconified(bool iconify) +{ + if (iconify) + { + KWindowSystem::minimizeWindow(d->win); + } + else + { + KWindowInfo info = KWindowSystem::windowInfo(d->win, NET::WMState | NET::XAWMState | NET::WMDesktop); + bool on_current = info.isOnCurrentDesktop(); + + if (!on_current) + { + KWindowSystem::setCurrentDesktop(info.desktop()); + } + + KWindowSystem::unminimizeWindow(d->win); + + if (!on_current) + { + KWindowSystem::forceActiveWindow(d->win); + } + } +} + +void Task::toggleIconified() +{ + setIconified(!isIconified()); +} + +void Task::close() +{ + NETRootInfo ri( QX11Info::display(), NET::CloseWindow ); + ri.closeWindowRequest( d->win ); +} + +void Task::raise() +{ +// kDebug(1210) << "Task::raise(): " << name(); + KWindowSystem::raiseWindow( d->win ); +} + +void Task::lower() +{ +// kDebug(1210) << "Task::lower(): " << name(); + KWindowSystem::lowerWindow( d->win ); +} + +void Task::activate() +{ +// kDebug(1210) << "Task::activate():" << name(); + WId w = d->win; + if (d->transientsDemandingAttention.count() > 0) + { + w = d->transientsDemandingAttention.last(); + } + KWindowSystem::forceActiveWindow( w ); +} + +void Task::activateRaiseOrIconify() +{ + if (!isActive() || isIconified()) + { + activate(); + } + else if (!isOnTop()) + { + raise(); + } + else + { + setIconified(true); + } +} + +void Task::toDesktop(int desk) +{ + NETWinInfo ni(QX11Info::display(), d->win, QX11Info::appRootWindow(), NET::WMDesktop); + if (desk == 0) + { + if (d->info.valid() && d->info.onAllDesktops()) + { + ni.setDesktop(KWindowSystem::currentDesktop()); + KWindowSystem::forceActiveWindow(d->win); + } + else + { + ni.setDesktop(NETWinInfo::OnAllDesktops); + } + + return; + } + ni.setDesktop(desk); + if(desk == KWindowSystem::currentDesktop()) + KWindowSystem::forceActiveWindow(d->win); +} + +void Task::toCurrentDesktop() +{ + toDesktop(KWindowSystem::currentDesktop()); +} + +void Task::setAlwaysOnTop(bool stay) +{ + NETWinInfo ni( QX11Info::display(), d->win, QX11Info::appRootWindow(), NET::WMState); + if(stay) + ni.setState( NET::StaysOnTop, NET::StaysOnTop ); + else + ni.setState( 0, NET::StaysOnTop ); +} + +void Task::toggleAlwaysOnTop() +{ + setAlwaysOnTop( !isAlwaysOnTop() ); +} + +void Task::setKeptBelowOthers(bool below) +{ + NETWinInfo ni(QX11Info::display(), d->win, QX11Info::appRootWindow(), NET::WMState); + + if (below) + { + ni.setState(NET::KeepBelow, NET::KeepBelow); + } + else + { + ni.setState(0, NET::KeepBelow); + } +} + +void Task::toggleKeptBelowOthers() +{ + setKeptBelowOthers(!isKeptBelowOthers()); +} + +void Task::setFullScreen(bool fullscreen) +{ + NETWinInfo ni(QX11Info::display(), d->win, QX11Info::appRootWindow(), NET::WMState); + + if (fullscreen) + { + ni.setState(NET::FullScreen, NET::FullScreen); + } + else + { + ni.setState(0, NET::FullScreen); + } +} + +void Task::toggleFullScreen() +{ + setFullScreen(!isFullScreen()); +} + +void Task::setShaded(bool shade) +{ + NETWinInfo ni( QX11Info::display(), d->win, QX11Info::appRootWindow(), NET::WMState); + if(shade) + ni.setState( NET::Shaded, NET::Shaded ); + else + ni.setState( 0, NET::Shaded ); +} + +void Task::toggleShaded() +{ + setShaded( !isShaded() ); +} + +void Task::publishIconGeometry(QRect rect) +{ + if (rect == d->iconGeometry) + { + return; + } + + d->iconGeometry = rect; + NETWinInfo ni(QX11Info::display(), d->win, QX11Info::appRootWindow(), 0); + NETRect r; + + if (rect.isValid()) + { + r.pos.x = rect.x(); + r.pos.y = rect.y(); + r.size.width = rect.width(); + r.size.height = rect.height(); + } + ni.setIconGeometry(r); +} + +#ifdef THUMBNAILING_POSSIBLE +QPixmap Task::thumbnail(int maxDimension) +{ + if (!KWindowSystem::compositingActive() || !d->windowPixmap) + { + return QPixmap(); + } + + Display *dpy = QX11Info::display(); + + XWindowAttributes winAttr; + XGetWindowAttributes(dpy, d->frameId, &winAttr); + XRenderPictFormat *format = XRenderFindVisualFormat(dpy, winAttr.visual); + + XRenderPictureAttributes picAttr; + ::memset(&picAttr, 0, sizeof(picAttr)); + picAttr.subwindow_mode = IncludeInferiors; // Don't clip child widgets + + Picture picture = XRenderCreatePicture(dpy, d->windowPixmap, format, + CPSubwindowMode, &picAttr); + + // Get shaped windows handled correctly. + XserverRegion region = XFixesCreateRegionFromWindow(dpy, d->frameId, + WindowRegionBounding); + XFixesSetPictureClipRegion(dpy, picture, 0, 0, region); + XFixesDestroyRegion(dpy, region); + + double factor; + if (winAttr.width > winAttr.height) + { + factor = (double)maxDimension / (double)winAttr.width; + } + else + { + factor = (double)maxDimension / (double)winAttr.height; + } + int thumbnailWidth = (int)(winAttr.width * factor); + int thumbnailHeight = (int)(winAttr.height * factor); + + QPixmap thumbnail(thumbnailWidth, thumbnailHeight); + thumbnail.fill(QApplication::palette().color(QPalette::Active,QPalette::Background)); + +#if 0 // QImage::smoothScale() scaling + QPixmap full(winAttr.width, winAttr.height); + full.fill(QApplication::palette().active().background()); + + bool hasAlpha = format->type == PictTypeDirect && format->direct.alphaMask; + + XRenderComposite(dpy, + hasAlpha ? PictOpOver : PictOpSrc, + picture, // src + None, // mask + full.x11RenderHandle(), // dst + 0, 0, // src offset + 0, 0, // mask offset + 0, 0, // dst offset + winAttr.width, winAttr.height); + + KPixmapIO io; + QImage image = io.toImage(full); + thumbnail = io.convertToPixmap(image.smoothScale(thumbnailWidth, + thumbnailHeight)); +#else // XRENDER scaling + // Scaling matrix + XTransform transformation = {{ + { XDoubleToFixed(1), XDoubleToFixed(0), XDoubleToFixed( 0) }, + { XDoubleToFixed(0), XDoubleToFixed(1), XDoubleToFixed( 0) }, + { XDoubleToFixed(0), XDoubleToFixed(0), XDoubleToFixed(factor) } + }}; + + XRenderSetPictureTransform(dpy, picture, &transformation); + XRenderSetPictureFilter(dpy, picture, FilterBest, 0, 0); + + XRenderComposite(QX11Info::display(), + PictOpOver, // we're filtering, alpha values are probable + picture, // src + None, // mask + thumbnail.x11PictureHandle(), // dst + 0, 0, // src offset + 0, 0, // mask offset + 0, 0, // dst offset + thumbnailWidth, thumbnailHeight); +#endif + XRenderFreePicture(dpy, picture); + + return thumbnail; +} +#else // THUMBNAILING_POSSIBLE +QPixmap Task::thumbnail(int /* maxDimension */) +{ + return QPixmap(); +} +#endif // THUMBNAILING_POSSIBLE + +void Task::updateWindowPixmap() +{ +#ifdef THUMBNAILING_POSSIBLE + if (!KWindowSystem::compositingActive() || !isOnCurrentDesktop() || + isMinimized()) + { + return; + } + + Display *dpy = QX11Info::display(); + + if (d->windowPixmap) + { + XFreePixmap(dpy, d->windowPixmap); + } + + d->windowPixmap = XCompositeNameWindowPixmap(dpy, d->frameId); +#endif // THUMBNAILING_POSSIBLE +} + +int TaskManager::currentDesktop() const +{ + return KWindowSystem::currentDesktop(); +} + +TaskDrag::TaskDrag(const TaskList& tasks, QWidget* source) + : QDrag(source), + d(0) +{ + QByteArray data; + QDataStream stream(&data, QIODevice::WriteOnly); + + stream.setVersion(QDataStream::Qt_3_1); + + TaskList::const_iterator itEnd = tasks.constEnd(); + for (TaskList::const_iterator it = tasks.constBegin(); it != itEnd; ++it) + { + stream << (quint32)(*it)->window(); + } + + QMimeData* mimeData = new QMimeData(); + mimeData->setData("taskbar/task", data); + setMimeData(mimeData); +} + +TaskDrag::~TaskDrag() +{ +} + +bool TaskDrag::canDecode(const QMimeData* e) +{ + return e->hasFormat("taskbar/task"); +} + +TaskList TaskDrag::decode( const QMimeData* e ) +{ + QByteArray data(e->data("taskbar/task")); + TaskList tasks; + + if (data.size()) + { + QDataStream stream(data); + while (!stream.atEnd()) + { + quint32 id; + stream >> id; + if (TaskPtr task = TaskManager::self()->findTask(id)) + { + tasks.append(task); + } + } + } + + return tasks; +} + +} // TaskManager namespace + +#include "task.moc" + diff --git a/taskmanager/task.h b/taskmanager/task.h new file mode 100644 index 000000000..f9a822252 --- /dev/null +++ b/taskmanager/task.h @@ -0,0 +1,440 @@ +/***************************************************************** + +Copyright (c) 2000-2001 Matthias Elter +Copyright (c) 2001 Richard Moore + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************/ + +#ifndef TASK_H +#define TASK_H + +// Qt +#include +#include +#include +#include + +// KDE +#include +#include +#include + +#include +#include + +namespace TaskManager +{ + +/** + * A dynamic interface to a task (main window). + * + * @see TaskManager + */ +class TASKMANAGER_EXPORT Task : public QObject, public KShared +{ + Q_OBJECT + Q_PROPERTY( QString visibleName READ visibleName ) + Q_PROPERTY( QString name READ name ) + Q_PROPERTY( QString className READ className ) + Q_PROPERTY( QString visibleNameWithState READ visibleNameWithState ) + Q_PROPERTY( QPixmap pixmap READ pixmap ) + Q_PROPERTY( bool maximized READ isMaximized ) + Q_PROPERTY( bool minimized READ isMinimized ) + // KDE4 deprecated + Q_PROPERTY( bool iconified READ isIconified ) + Q_PROPERTY( bool shaded READ isShaded WRITE setShaded ) + Q_PROPERTY( bool active READ isActive ) + Q_PROPERTY( bool onCurrentDesktop READ isOnCurrentDesktop ) + Q_PROPERTY( bool onAllDesktops READ isOnAllDesktops ) + Q_PROPERTY( bool alwaysOnTop READ isAlwaysOnTop WRITE setAlwaysOnTop ) + Q_PROPERTY( bool modified READ isModified ) + Q_PROPERTY( bool demandsAttention READ demandsAttention ) + Q_PROPERTY( int desktop READ desktop ) + Q_PROPERTY( double thumbnailSize READ thumbnailSize WRITE setThumbnailSize ) + Q_PROPERTY( bool hasThumbnail READ hasThumbnail ) + Q_PROPERTY( QPixmap thumbnail READ thumbnail ) + +public: + Task(WId win, QObject *parent, const char *name = 0); + virtual ~Task(); + + WId window() const; + KWindowInfo info() const; + + QString visibleName() const; + QString visibleNameWithState() const; + QString name() const; + QString className() const; + QString classClass() const; + + /** + * A list of the window ids of all transient windows (dialogs) associated + * with this task. + */ + WindowList transients() const; + + /** + * Returns a 16x16 (KIconLoader::Small) icon for the task. This method will + * only fall back to a static icon if there is no icon of any size in + * the WM hints. + */ + QPixmap pixmap() const; + + /** + * Returns the best icon for any of the KIconLoader::StdSizes. If there is no + * icon of the specified size specified in the WM hints, it will try to + * get one using KIconLoader. + * + *
    +     *   bool gotStaticIcon;
    +     *   QPixmap icon = myTask->icon( KIconLoader::SizeMedium, gotStaticIcon );
    +     * 
    + * + * @param size Any of the constants in KIconLoader::StdSizes. + * @param isStaticIcon Set to true if KIconLoader was used, false otherwise. + */ + QPixmap bestIcon( int size, bool &isStaticIcon ); + + /** + * Tries to find an icon for the task with the specified size. If there + * is no icon that matches then it will either resize the closest available + * icon or return a null pixmap depending on the value of allowResize. + * + * Note that the last icon is cached, so a sequence of calls with the same + * parameters will only query the NET properties if the icon has changed or + * none was found. + */ + QPixmap icon( int width, int height, bool allowResize = false ); + + /** + * \return a QIcon for the task + */ + QIcon icon(); + + /** + * Returns true iff the windows with the specified ids should be grouped + * together in the task list. + */ + static bool idMatch(const QString &, const QString &); + + // state + + /** + * Returns true if the task's window is maximized. + */ + bool isMaximized() const; + + /** + * Returns true if the task's window is minimized. + */ + bool isMinimized() const; + + /** + * @deprecated + * Returns true if the task's window is minimized(iconified). + */ + bool isIconified() const; + + /** + * Returns true if the task's window is shaded. + */ + bool isShaded() const; + + /** + * Returns true if the task's window is the active window. + */ + bool isActive() const; + + /** + * Returns true if the task's window is the topmost non-iconified, + * non-always-on-top window. + */ + bool isOnTop() const; + + /** + * Returns true if the task's window is on the current virtual desktop. + */ + bool isOnCurrentDesktop() const; + + /** + * Returns true if the task's window is on all virtual desktops. + */ + bool isOnAllDesktops() const; + + /** + * Returns true if the task's window will remain at the top of the + * stacking order. + */ + bool isAlwaysOnTop() const; + + /** + * Returns true if the task's window will remain at the bottom of the + * stacking order. + */ + bool isKeptBelowOthers() const; + + /** + * Returns true if the task's window is in full screen mode + */ + bool isFullScreen() const; + + /** + * Returns true if the document the task is editing has been modified. + * This is currently handled heuristically by looking for the string + * '[i18n_modified]' in the window title where i18n_modified is the + * word 'modified' in the current language. + */ + bool isModified() const ; + + /** + * Returns the desktop on which this task's window resides. + */ + int desktop() const; + + /** + * Returns true if the task is not active but demands user's attention. + */ + bool demandsAttention() const; + + + /** + * Returns true if the window is on the specified screen of a multihead configuration + */ + bool isOnScreen( int screen ) const; + + /** + * Returns true if the task should be shown in taskbar-like apps + */ + bool showInTaskbar() const; + + /** + * Returns true if the task should be shown in pager-like apps + */ + bool showInPager() const; + + /** + * Returns the geometry for this window + */ + QRect geometry() const; + + // internal + + //* @internal + ::TaskManager::TaskChanges refresh(unsigned int dirty); + //* @internal + void refreshIcon(); + //* @internal + void addTransient( WId w, const NETWinInfo& info ); + //* @internal + void removeTransient( WId w ); + //* @internal + bool hasTransient(WId w) const; + //* @internal + void updateDemandsAttentionState( WId w ); + //* @internal + void setActive(bool a); + + // For thumbnails + + /** + * Returns the current thumbnail size. + */ + double thumbnailSize() const; + + /** + * Sets the size for the window thumbnail. For example a size of + * 0.2 indicates the thumbnail will be 20% of the original window + * size. + */ + void setThumbnailSize( double size ); + + /** + * Returns true if this task has a thumbnail. Note that this method + * can only ever return true after a call to updateThumbnail(). + */ + bool hasThumbnail() const; + + /** + * Returns the thumbnail for this task (or a null image if there is + * none). + */ + QPixmap thumbnail() const; + + QPixmap thumbnail(int maxDimension); + + void updateWindowPixmap(); + +public Q_SLOTS: + // actions + + /** + * Maximise the main window of this task. + */ + void setMaximized(bool); + void toggleMaximized(); + + /** + * Restore the main window of the task (if it was iconified). + */ + void restore(); + + /** + * Move the window of this task. + */ + void move(); + + /** + * Resize the window of this task. + */ + void resize(); + + /** + * Iconify the task. + */ + void setIconified(bool); + void toggleIconified(); + + /** + * Close the task's window. + */ + void close(); + + /** + * Raise the task's window. + */ + void raise(); + + /** + * Lower the task's window. + */ + void lower(); + + /** + * Activate the task's window. + */ + void activate(); + + /** + * Perform the action that is most appropriate for this task. If it + * is not active, activate it. Else if it is not the top window, raise + * it. Otherwise, iconify it. + */ + void activateRaiseOrIconify(); + + /** + * If true, the task's window will remain at the top of the stacking order. + */ + void setAlwaysOnTop(bool); + void toggleAlwaysOnTop(); + + /** + * If true, the task's window will remain at the bottom of the stacking order. + */ + void setKeptBelowOthers(bool); + void toggleKeptBelowOthers(); + + /** + * If true, the task's window will enter full screen mode. + */ + void setFullScreen(bool); + void toggleFullScreen(); + + /** + * If true then the task's window will be shaded. Most window managers + * represent this state by displaying on the window's title bar. + */ + void setShaded(bool); + void toggleShaded(); + + /** + * Moves the task's window to the specified virtual desktop. + */ + void toDesktop(int); + + /** + * Moves the task's window to the current virtual desktop. + */ + void toCurrentDesktop(); + + /** + * This method informs the window manager of the location at which this + * task will be displayed when iconised. It is used, for example by the + * KWin inconify animation. + */ + void publishIconGeometry(QRect); + +Q_SIGNALS: + /** + * Indicates that this task has changed in some way. + */ + void changed(::TaskManager::TaskChanges change); + + /** + * Indicates that this task is now the active task. + */ + void activated(); + + /** + * Indicates that this task is no longer the active task. + */ + void deactivated(); + +protected: + void findWindowFrameId(); + +private: + class Private; + Private * const d; +}; + + +/** + * Provids a drag object for tasks across desktops. + * FIXME: should be folded into the Task class the same way it has been with + * AppletInfo and KUrl + */ +class TASKMANAGER_EXPORT TaskDrag : public QDrag +{ +public: + /** + * Constructs a task drag object for a task list. + */ + explicit TaskDrag(const TaskList& tasks, QWidget* source = 0); + ~TaskDrag(); + + /** + * Returns true if the mime source can be decoded to a TaskDrag. + */ + static bool canDecode( const QMimeData* e ); + + /** + * Decodes the tasks from the mime source and returns them if successful. + * Otherwise an empty task list is returned. + */ + static TaskList decode( const QMimeData* e ); + +private: + class Private; + Private * const d; +}; + +} // TaskManager namespace + +#endif diff --git a/taskmanager/taskactions.cpp b/taskmanager/taskactions.cpp new file mode 100644 index 000000000..b37af079b --- /dev/null +++ b/taskmanager/taskactions.cpp @@ -0,0 +1,422 @@ +/***************************************************************** + +Copyright 2008 Christian Mollekopf + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************/ + +#include "taskactions.h" +#include "taskactions_p.h" + +// Own + +#include "taskgroup.h" +#include "task.h" +#include "taskitem.h" +#include "taskmanager.h" +#include "abstractgroupingstrategy.h" + +// KDE +#include +#include +#include + +namespace TaskManager +{ + + +QAction *standardGroupableAction(GroupableAction action, AbstractItemPtr item, QObject *parent, int desktop) +{ + Q_ASSERT(item); + + switch (action) { + case MaximizeAction: + return new MaximizeActionImpl(parent, item); + break; + case MinimizeAction: + return new MinimizeActionImpl(parent, item); + break; + case ToCurrentDesktopAction: + return new ToCurrentDesktopActionImpl(parent, item); + break; + case ToDesktopAction: + return new ToDesktopActionImpl(parent, item, desktop); + break; + case ShadeAction: + return new ShadeActionImpl(parent, item); + break; + case CloseAction: + return new CloseActionImpl(parent, item); + break; + case ViewFullscreenAction: + return new ViewFullscreenActionImpl(parent, item); + break; + case KeepBelowAction: + return new KeepBelowActionImpl(parent, item); + break; + } + + return 0; +} + +QAction* standardTaskAction(TaskAction action, TaskItem *item, QObject *parent) +{ + Q_ASSERT(item); + + switch (action) { + case ResizeAction: + return new ResizeActionImpl(parent, item); + break; + case MoveAction: + return new MoveActionImpl(parent, item); + break; + } + + return 0; +} + +QAction* standardGroupingAction(GroupingAction action, AbstractItemPtr item, GroupManager *strategy, QObject *parent) +{ + Q_ASSERT(item); + Q_ASSERT(strategy); + + switch (action) { + case LeaveGroupAction: + return new LeaveGroupActionImpl(parent, item, strategy); + break; + } + + return 0; +} + +MinimizeActionImpl::MinimizeActionImpl(QObject *parent, AbstractItemPtr item) + : QAction(parent) +{ + connect(this, SIGNAL(triggered()), item, SLOT(toggleMinimized())); + setText(i18n("Mi&nimize")); + setCheckable(true); + setChecked(item->isMinimized()); + setEnabled(item->isActionSupported(NET::ActionMinimize)); +} + + +MaximizeActionImpl::MaximizeActionImpl(QObject *parent, AbstractItemPtr item) + : QAction(parent) +{ + connect(this, SIGNAL(triggered()), item, SLOT(toggleMaximized())); + setText(i18n("Ma&ximize")); + setCheckable(true); + setChecked(item->isMaximized()); + setEnabled(item->isActionSupported(NET::ActionMax)); +} + +ShadeActionImpl::ShadeActionImpl(QObject *parent, AbstractItemPtr item) + : QAction(parent) +{ + connect(this, SIGNAL(triggered()), item, SLOT(toggleShaded())); + setText(i18n("&Shade")); + setCheckable(true); + setChecked(item->isShaded()); + setEnabled(item->isActionSupported(NET::ActionShade)); +} + +ResizeActionImpl::ResizeActionImpl(QObject *parent, TaskItem* item) + : QAction(parent) +{ + TaskPtr task = item->task(); + connect(this, SIGNAL(triggered()), task.data(), SLOT(resize())); + setText(i18n("Re&size")); + setEnabled(item->isActionSupported(NET::ActionResize)); +} + +MoveActionImpl::MoveActionImpl(QObject *parent, TaskItem* item) + : QAction(parent) +{ + TaskPtr task = item->task(); + connect(this, SIGNAL(triggered()), task.data(), SLOT(move())); + setText(i18n("&Move")); + setIcon(KIcon("transform-move")); + setEnabled(item->isActionSupported(NET::ActionMove)); +} + +CloseActionImpl::CloseActionImpl(QObject *parent, AbstractItemPtr item) + : QAction(parent) +{ + connect(this, SIGNAL(triggered()), item, SLOT(close())); + setText(i18n("&Close")); + setIcon(KIcon("window-close")); + setEnabled(item->isActionSupported(NET::ActionClose)); +} + + +ToCurrentDesktopActionImpl::ToCurrentDesktopActionImpl(QObject *parent, AbstractItemPtr item) + : QAction(parent), + m_item(item) +{ + connect(this, SIGNAL(triggered()), this, SLOT(slotToCurrentDesktop())); + setText(i18n("&To Current Desktop")); + setEnabled(!item->isOnCurrentDesktop() && item->isActionSupported(NET::ActionChangeDesktop)); +} + +void ToCurrentDesktopActionImpl::slotToCurrentDesktop() +{ + m_item->toDesktop(KWindowSystem::currentDesktop()); +} + + + +ToDesktopActionImpl::ToDesktopActionImpl(QObject *parent, AbstractItemPtr item, int desktop) + : QAction(parent), + m_desktop(desktop), + m_item(item) +{ + connect(this, SIGNAL(triggered()), this, SLOT(slotToDesktop())); + setCheckable(true); + if (!desktop) { //to All Desktops + setText(i18n("&All Desktops")); + setChecked(item->isOnAllDesktops()); + } else { + QString name = QString("&%1 %2").arg(desktop).arg(TaskManager::self()->desktopName(desktop).replace('&', "&&")); + setText(name); + setChecked(!item->isOnAllDesktops() && item->desktop() == desktop); + } + +} + +void ToDesktopActionImpl::slotToDesktop() +{ + m_item->toDesktop(m_desktop); +} + + + +DesktopsMenu::DesktopsMenu(QWidget *parent, AbstractItemPtr item) + : QMenu(parent) +{ + setTitle( i18n("To &Desktop") ); + addAction( new ToDesktopActionImpl(this,item,0) ); //0 means all desktops + addSeparator(); + for (int i = 1; i <= TaskManager::self()->numberOfDesktops(); i++) { + addAction( new ToDesktopActionImpl(this,item,i) ); + } + setEnabled(item->isActionSupported(NET::ActionChangeDesktop)); +} + +KeepAboveActionImpl::KeepAboveActionImpl(QObject *parent, AbstractItemPtr item) + : QAction(parent) +{ + connect(this, SIGNAL(triggered()), item, SLOT(toggleAlwaysOnTop())); + setText(i18n("Keep &Above Others")); + setIcon(KIcon("go-up")); + setCheckable(true); + setChecked(item->isAlwaysOnTop()); +} + +KeepBelowActionImpl::KeepBelowActionImpl(QObject *parent, AbstractItemPtr item) + : QAction(parent) +{ + connect(this, SIGNAL(triggered()), item, SLOT(toggleKeptBelowOthers())); + setText(i18n("Keep &Below Others")); + setIcon(KIcon("go-down")); + setCheckable(true); + setChecked(item->isKeptBelowOthers()); +} + +ViewFullscreenActionImpl::ViewFullscreenActionImpl(QObject *parent, AbstractItemPtr item) + : QAction(parent) +{ + connect(this, SIGNAL(triggered()), item, SLOT(toggleFullScreen())); + setText(i18n("&Fullscreen")); + setIcon(KIcon("view-fullscreen")); + setCheckable(true); + setChecked(item->isFullScreen()); + setEnabled(item->isActionSupported(NET::ActionFullScreen)); +} + +AdvancedMenu::AdvancedMenu(QWidget *parent, AbstractItemPtr item) + :QMenu(parent) +{ + setTitle(i18n("Ad&vanced")); + addAction(new KeepAboveActionImpl(this, item)); + addAction(new KeepBelowActionImpl(this, item)); + addAction(new ViewFullscreenActionImpl(this, item)); +} + +LeaveGroupActionImpl::LeaveGroupActionImpl(QObject *parent, AbstractItemPtr item, GroupManager *strategy) + : QAction(parent), abstractItem(item), groupingStrategy(strategy) +{ + Q_ASSERT(strategy); + connect(this, SIGNAL(triggered()), this, SLOT(leaveGroup())); + setText(i18n("&Leave Group")); + setIcon(KIcon("window-close")); + setEnabled(item->isGrouped()); +} + +void LeaveGroupActionImpl::leaveGroup() +{ + groupingStrategy->manualGroupingRequest(abstractItem,abstractItem->parentGroup()->parentGroup()); +} + +EditGroupActionImpl::EditGroupActionImpl(QObject *parent, TaskGroup *group, GroupManager *groupManager) + : QAction(parent) +{ + Q_ASSERT(groupManager); + connect(this, SIGNAL(triggered()), group, SIGNAL(groupEditRequest())); + setText(i18n("&Edit Group")); + //setIcon(KIcon("window-close")); + if (groupManager->groupingStrategy()) { + setEnabled(groupManager->taskGrouper()->editableGroupProperties()); + } else { + setEnabled(false); + } +} + +GroupingStrategyMenu::GroupingStrategyMenu(QWidget *parent, AbstractGroupableItem* item, GroupManager *strategy) + : QMenu(parent) +{ + Q_ASSERT(item); + Q_ASSERT(strategy); + + setTitle("Grouping strategy actions"); + if (strategy->taskGrouper()) { + QList groupingStrategyActions = strategy->taskGrouper()->strategyActions(this, item); + if (!groupingStrategyActions.empty()) { + addSeparator(); + foreach (QAction *action, groupingStrategyActions) { + addAction(action); + } + } + } + +} + + +BasicMenu::BasicMenu(QWidget *parent, TaskItem* item, GroupManager *strategy, QList visualizationActions) + : QMenu(parent) +{ + Q_ASSERT(item); + Q_ASSERT(strategy); + + setTitle(item->name()); + setIcon(item->icon()); + addMenu(new AdvancedMenu(this, item)); + + if (TaskManager::self()->numberOfDesktops() > 1) { + addMenu(new DesktopsMenu(this, item)); + addAction(new ToCurrentDesktopActionImpl(this, item)); + } + + addAction(new MoveActionImpl(this, item)); + addAction(new ResizeActionImpl(this, item)); + addAction(new MinimizeActionImpl(this, item)); + addAction(new MaximizeActionImpl(this, item)); + addAction(new ShadeActionImpl(this, item)); + + if (strategy->taskGrouper()) { + QList groupingStrategyActions = strategy->taskGrouper()->strategyActions(this, item); + if (!groupingStrategyActions.isEmpty()) { + addSeparator(); + foreach (QAction *action, groupingStrategyActions) { + addAction(action); + } + // delete groupingStrategyActions; + } + } + + foreach (QAction *action, visualizationActions) { + addAction(action); + } + + addSeparator(); + addAction(new CloseActionImpl(this, item)); +} + +BasicMenu::BasicMenu(QWidget *parent, TaskGroup* group, GroupManager *strategy, QList visualizationActions) + :QMenu(parent) +{ + Q_ASSERT(group); + Q_ASSERT(strategy); + + setTitle(group->name()); + setIcon(group->icon()); + foreach (AbstractGroupableItem *item, group->members()) { + if (item->isGroupItem()) { + addMenu(new BasicMenu(this, dynamic_cast(item), strategy)); + } else { + addMenu(new BasicMenu(this, dynamic_cast(item), strategy)); + } + } + addSeparator(); + addMenu(new AdvancedMenu(this, group)); + + if (TaskManager::self()->numberOfDesktops() > 1) { + addMenu(new DesktopsMenu(this, group)); + addAction(new ToCurrentDesktopActionImpl(this, group)); + } + + addAction(new MinimizeActionImpl(this, group)); + addAction(new MaximizeActionImpl(this, group)); + addAction(new ShadeActionImpl(this, group)); + + if (strategy->taskGrouper()) { + QList groupingStrategyActions = strategy->taskGrouper()->strategyActions(this, group); + if (!groupingStrategyActions.isEmpty()) { + addSeparator(); + foreach (QAction *action, groupingStrategyActions) { + addAction(action); + } + } + } + addAction(new EditGroupActionImpl(this, group, strategy)); + foreach(QAction *action, visualizationActions) { + addAction(action); + } + + addSeparator(); + addAction(new CloseActionImpl(this, group)); + +} + +GroupPopupMenu::GroupPopupMenu(QWidget *parent, TaskGroup *group, GroupManager *groupManager) + :QMenu(parent) +{ + setTitle(group->name()); + setIcon(group->icon()); + foreach (AbstractGroupableItem *item, group->members()) { + if (!item) { + kDebug() << "invalid Item"; + continue; + } + + if (item->isGroupItem()) { + QMenu* menu = new GroupPopupMenu (this, qobject_cast(item), groupManager); + addMenu(menu); + } else { + QAction* action = new QAction(item->icon(), item->name(), this); + connect(action, SIGNAL(triggered(bool)), (qobject_cast(item))->task().data() , SLOT(activateRaiseOrIconify())); + addAction(action); + } + } +} + +} // TaskManager namespace + +#include "taskactions.moc" +#include "taskactions_p.moc" + diff --git a/taskmanager/taskactions.h b/taskmanager/taskactions.h new file mode 100644 index 000000000..6e79c904f --- /dev/null +++ b/taskmanager/taskactions.h @@ -0,0 +1,133 @@ +/***************************************************************** + +Copyright 2008 Christian Mollekopf + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************/ + +#ifndef TASKACTIONS_H +#define TASKACTIONS_H + +// Qt +#include +#include + +// Own +#include +#include +#include +#include +#include + +namespace TaskManager +{ + +enum GroupableAction { MaximizeAction = 0, + MinimizeAction, + ToCurrentDesktopAction, + ToDesktopAction, + ShadeAction, + CloseAction, + ViewFullscreenAction, + KeepBelowAction + }; + +enum TaskAction { ResizeAction = 0, + MoveAction + }; + +enum GroupingAction { LeaveGroupAction = 0 + }; + +/** + * Factory method to create standard actions for groupable items. + * + * @param action the action to create + * @param item the groupable item to associate it with + * @param parent the parent for the action + * @param desktop the desktop to associate the action with, only used for ToDesktopAction + */ +QAction *standardGroupableAction(GroupableAction action, AbstractItemPtr item, QObject *parent = 0, int desktop = 0); + +/** + * Factory method to create standard actions for groupable items. + * + * @param action the action to create + * @param task the task to associate it with + * @param parent the parent for the action + */ +QAction *standardTaskAction(TaskAction action, TaskItem *task, QObject *parent = 0); + +/** + * Factory method to create standard actions for groupable items. + * + * @param action the action to create + * @param item the groupable item to associate it with + * @param strategy the GroupManager used to coorinate the grouping + * @param parent the parent for the action + */ +QAction* standardGroupingAction(GroupingAction action, AbstractItemPtr item, + GroupManager *strategy, QObject *parent = 0); + +/** The ToDesktop menu */ +class TASKMANAGER_EXPORT DesktopsMenu : public QMenu +{ + Q_OBJECT +public: + DesktopsMenu(QWidget *parent, AbstractItemPtr task); +}; + +/** Menu with the actions that the groupingStrategy provides*/ +class TASKMANAGER_EXPORT GroupingStrategyMenu : public QMenu +{ + Q_OBJECT +public: + GroupingStrategyMenu(QWidget *parent, AbstractGroupableItem *task, GroupManager *strategy); +}; + +/** The Advanced menu */ +class TASKMANAGER_EXPORT AdvancedMenu : public QMenu +{ + Q_OBJECT +public: + AdvancedMenu(QWidget *parent, AbstractItemPtr task); +}; + +/** The standard menu*/ +class TASKMANAGER_EXPORT BasicMenu : public QMenu +{ + Q_OBJECT +public: + BasicMenu(QWidget *parent, GroupPtr task, GroupManager *strategy, QList visualizationActions = QList ()); + BasicMenu(QWidget *parent, TaskItem* task, GroupManager *strategy, QList visualizationActions = QList ()); +}; + +/** A Menu that shows a list of all tasks of the group, and shows a BasicMenu on right click on an item*/ +class TASKMANAGER_EXPORT GroupPopupMenu : public QMenu +{ + Q_OBJECT +public: + GroupPopupMenu(QWidget *parent, GroupPtr task, GroupManager *strategy); +}; + + +} // TaskManager namespace + + +#endif diff --git a/taskmanager/taskactions_p.h b/taskmanager/taskactions_p.h new file mode 100644 index 000000000..9ac42877f --- /dev/null +++ b/taskmanager/taskactions_p.h @@ -0,0 +1,165 @@ +/***************************************************************** + +Copyright 2008 Christian Mollekopf + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************/ + +#ifndef TASKACTIONS_P_H +#define TASKACTIONS_P_H + +namespace TaskManager +{ + +/** Maximize a window or all windows in a group*/ +class MaximizeActionImpl : public QAction +{ + Q_OBJECT +public: + MaximizeActionImpl(QObject *parent, AbstractItemPtr task); +}; + + +/** Minimize a window or all windows in a group*/ +class MinimizeActionImpl : public QAction +{ + Q_OBJECT +public: + MinimizeActionImpl(QObject *parent, AbstractItemPtr task); +}; + +/** Move window to current desktop*/ +class ToCurrentDesktopActionImpl : public QAction +{ + Q_OBJECT +public: + ToCurrentDesktopActionImpl(QObject *parent, AbstractItemPtr task); +private Q_SLOTS: + void slotToCurrentDesktop(); +private: + AbstractItemPtr m_item; +}; + +/** Shade a window or all windows in a group*/ +class ShadeActionImpl : public QAction +{ + Q_OBJECT +public: + ShadeActionImpl(QObject *parent, AbstractItemPtr task); +}; + +/** Resize a window or all windows in a group*/ +class ResizeActionImpl : public QAction +{ + Q_OBJECT +public: + ResizeActionImpl(QObject *parent, TaskItem* task); +}; + +/** Move a window or all windows in a group*/ +class MoveActionImpl : public QAction +{ + Q_OBJECT +public: + MoveActionImpl(QObject *parent, TaskItem* task); +}; + +/** Shade a window or all windows in a group*/ +class CloseActionImpl : public QAction +{ + Q_OBJECT +public: + CloseActionImpl(QObject *parent, AbstractItemPtr task); +}; + +/** Send a Task to a specific Desktop*/ +class ToDesktopActionImpl : public QAction +{ + Q_OBJECT +public: + ToDesktopActionImpl(QObject *parent, AbstractItemPtr task, int desktop); +private Q_SLOTS: + void slotToDesktop(); +private: + int m_desktop; + AbstractItemPtr m_item; +}; + + +/** Set a window or all windows in a group to FullScreen*/ +class ViewFullscreenActionImpl : public QAction +{ + Q_OBJECT +public: + ViewFullscreenActionImpl(QObject *parent, AbstractItemPtr task); +}; + +/** Keep a Window or all windows in a group above the rest */ +class KeepAboveActionImpl : public QAction +{ + Q_OBJECT +public: + KeepAboveActionImpl(QObject *parent, AbstractItemPtr task); +}; + +/** Keep a Window or all windows in a group below the rest*/ +class KeepBelowActionImpl : public QAction +{ + Q_OBJECT +public: + KeepBelowActionImpl(QObject *parent, AbstractItemPtr task); +}; + + +/** Leave current Group*/ +class LeaveGroupActionImpl : public QAction +{ + Q_OBJECT +public: + LeaveGroupActionImpl(QObject *parent, AbstractItemPtr task, GroupManager*); + +private Q_SLOTS: + void leaveGroup(); + +private: + AbstractItemPtr abstractItem; + GroupManager *groupingStrategy; +}; + +/** Edit current Group*/ +class EditGroupActionImpl : public QAction +{ + Q_OBJECT +public: + EditGroupActionImpl(QObject *parent, TaskGroup *group, GroupManager*); +}; + +/** Remove Group +class RemoveGroupActionImpl : public QAction +{ + Q_OBJECT +public: + RemoveGroupActionImpl(QObject *parent, AbstractItemPtr task); +}; +*/ + +} // TaskManager namespace + + +#endif diff --git a/taskmanager/taskgroup.cpp b/taskmanager/taskgroup.cpp new file mode 100644 index 000000000..2c31c926d --- /dev/null +++ b/taskmanager/taskgroup.cpp @@ -0,0 +1,493 @@ +/***************************************************************** + +Copyright 2008 Christian Mollekopf + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************/ + +// Own +#include "taskgroup.h" +#include "taskmanager.h" +#include "taskitem.h" +#include "groupmanager.h" + +// Qt +#include + +// KDE +#include +#include +#include + + + +namespace TaskManager +{ + + +class TaskGroup::Private +{ +public: + Private() + { + } + + ItemList members; + QString groupName; + QColor groupColor; + QIcon groupIcon; + bool aboutToDie; + GroupManager *groupingStrategy; +}; + +TaskGroup::TaskGroup(GroupManager *parent,QString name, QColor color) +: AbstractGroupableItem(parent), + d(new Private) +{ + d->groupingStrategy = parent; + d->groupName = name; + d->groupColor = color; + d->groupIcon = KIcon("xorg"); + connect(this, SLOT(editRequest()), this, SIGNAL(groupEditRequest())); + kDebug() << "Group Created: Name: " << d->groupName << "Color: " << d->groupColor; +} + +TaskGroup::TaskGroup(GroupManager *parent) +: AbstractGroupableItem(parent), + d(new Private) +{ + d->groupingStrategy = parent; + d->groupName = "default"; + d->groupColor = Qt::red; + d->groupIcon = KIcon("xorg"); + connect(this, SLOT(editRequest()), this, SIGNAL(groupEditRequest())); + kDebug() << "Group Created: Name: " << d->groupName << "Color: " << d->groupColor; +} + + +TaskGroup::~TaskGroup() +{ + kDebug() << name(); + delete d; +} + + +void TaskGroup::add(AbstractItemPtr item) +{ +/* if (!item->isGroupItem()) { + if ((dynamic_cast(item))->task()) { + kDebug() << "Add item" << (dynamic_cast(item))->task()->visibleName(); + } + kDebug() << " to Group " << name(); + } +*/ + + if (d->members.contains(item)) { + kDebug() << "already in this group"; + return; + } + + if (item->parentGroup()) { + item->parentGroup()->remove(item); + } + + d->members.append(item); + item->setParentGroup(this); + + connect(item, SIGNAL(changed(::TaskManager::TaskChanges)), + this, SIGNAL(changed(::TaskManager::TaskChanges))); + //For debug + /* foreach (AbstractGroupableItem *item, d->members) { + if (item->isGroupItem()) { + kDebug() << (dynamic_cast(item))->name(); + } else { + kDebug() << (dynamic_cast(item))->task()->visibleName(); + } + }*/ + emit itemAdded(item); +} + + + +void TaskGroup::remove(AbstractItemPtr item) +{ + Q_ASSERT(item); + + if (item->isGroupItem()) { + kDebug() << "Remove group" << (dynamic_cast(item))->name(); + } else if ((dynamic_cast(item))->task()) { + kDebug() << "Remove item" << (dynamic_cast(item))->task()->visibleName(); + } + kDebug() << "from Group: " << name(); + + /* kDebug() << "GroupMembers: "; + foreach (AbstractGroupableItem *item, d->members) { + if (item->isGroupItem()) { + kDebug() << (dynamic_cast(item))->name(); + } else { + kDebug() << (dynamic_cast(item))->task()->visibleName(); + } + }*/ + + if (!d->members.contains(item)) { + kDebug() << "couldn't find item"; + return; + } + disconnect(item, 0, this, 0); + + d->members.removeAll(item); + item->setParentGroup(0); + /*if(d->members.isEmpty()){ + kDebug() << "empty"; + emit empty(this); + }*/ + emit itemRemoved(item); +} + +void TaskGroup::clear() +{ + // kDebug() << "size " << d->members.size(); + foreach(AbstractGroupableItem *item, d->members) { + // kDebug(); + Q_ASSERT(item); + if (item->isGroupItem()) { + (dynamic_cast(item))->clear(); + } + remove(item); + } + if (!d->members.isEmpty()) { + kDebug() << "clear doesn't work"; + } +} + +ItemList TaskGroup::members() const +{ + return d->members; +} + +void TaskGroup::setColor(const QColor &color) +{ + d->groupColor = color; + emit changed(ColorChanged); +} + +QColor TaskGroup::color() const +{ + return d->groupColor; +} + +QString TaskGroup::name() const +{ + return d->groupName; +} + +void TaskGroup::setName(const QString &newName) +{ + d->groupName = newName; + emit changed(NameChanged); +} + +QIcon TaskGroup::icon() const +{ + return d->groupIcon; +} + +void TaskGroup::setIcon(const QIcon &newIcon) +{ + d->groupIcon = newIcon; + emit changed(IconChanged); +} + +bool TaskGroup::isRootGroup() const +{ + return !parentGroup(); +} + +/** only true if item is in this group */ +bool TaskGroup::hasDirectMember(AbstractItemPtr item) const +{ + return d->members.contains(item); +} + +/** true if item is in this or any sub group */ +bool TaskGroup::hasMember(AbstractItemPtr item) const +{ + kDebug(); + TaskGroup *group = item->parentGroup(); + while (group) { + if (group == this) { + return true; + } + group = group->parentGroup(); + } + return false; +} + +/** Returns Direct Member group if the passed item is in a subgroup */ +AbstractItemPtr TaskGroup::directMember(AbstractItemPtr item) const +{ + AbstractItemPtr tempItem = item; + while (tempItem) { + if (d->members.contains(item)) { + return item; + } + tempItem = tempItem->parentGroup(); + } + kDebug() << "item not found"; + return AbstractItemPtr(); +} + +void TaskGroup::setShaded(bool state) +{ + foreach (AbstractItemPtr item, d->members) { + item->setShaded(state); + } +} + +void TaskGroup::toggleShaded() +{ + setShaded(!isShaded()); +} + +bool TaskGroup::isShaded() const +{ + foreach (AbstractItemPtr item, d->members) { + if (!item->isShaded()) { + return false; + } + } + return true; +} + +void TaskGroup::toDesktop(int desk) +{ + foreach (AbstractItemPtr item, d->members) { + item->toDesktop(desk); + } + emit movedToDesktop(desk); +} + +bool TaskGroup::isOnCurrentDesktop() const +{ + foreach (AbstractItemPtr item, d->members) { + if (!item->isOnCurrentDesktop()) { + return false; + } + } + return true; +} + +bool TaskGroup::isOnAllDesktops() const +{ + foreach (AbstractItemPtr item, d->members) { + if (!item->isOnAllDesktops()) { + return false; + } + } + return true; +} + +//return 0 if tasks are on different desktops or on all dektops +int TaskGroup::desktop() const +{ + if (d->members.isEmpty()) { + return 0; + } + + int desk = d->members.first()->desktop(); + foreach (AbstractItemPtr item, d->members) { + if (item->desktop() != desk) { + return 0; + } + desk = item->desktop(); + } + return desk; +} + +void TaskGroup::setMaximized(bool state) +{ + foreach (AbstractItemPtr item, d->members) { + item->setMaximized(state); + } +} + +void TaskGroup::toggleMaximized() +{ + setMaximized(!isMaximized()); +} + +bool TaskGroup::isMaximized() const +{ + foreach (AbstractItemPtr item, d->members) { + if (!item->isMaximized()) { + return false; + } + } + return true; +} + +void TaskGroup::setMinimized(bool state) +{ + foreach (AbstractItemPtr item, d->members) { + item->setMinimized(state); + } +} + +void TaskGroup::toggleMinimized() +{ + setMinimized(!isMinimized()); +} + +bool TaskGroup::isMinimized() const +{ + foreach (AbstractItemPtr item, d->members) { + if (!item->isMinimized()) { + return false; + } + } + return true; +} + +void TaskGroup::setFullScreen(bool state) +{ + foreach (AbstractItemPtr item, d->members) { + item->setFullScreen(state); + } +} + +void TaskGroup::toggleFullScreen() +{ + setFullScreen(!isFullScreen()); +} + +bool TaskGroup::isFullScreen() const +{ + foreach (AbstractItemPtr item, d->members) { + if (!item->isFullScreen()) { + return false; + } + } + return true; +} + +void TaskGroup::setKeptBelowOthers(bool state) +{ + foreach (AbstractItemPtr item, d->members) { + item->setKeptBelowOthers(state); + } +} + +void TaskGroup::toggleKeptBelowOthers() +{ + setKeptBelowOthers(!isKeptBelowOthers()); +} + +bool TaskGroup::isKeptBelowOthers() const +{ + foreach (AbstractItemPtr item, d->members) { + if (!item->isKeptBelowOthers()) { + return false; + } + } + return true; +} + +void TaskGroup::setAlwaysOnTop(bool state) +{ + foreach (AbstractItemPtr item, d->members) { + item->setAlwaysOnTop(state); + } +} + +void TaskGroup::toggleAlwaysOnTop() +{ + setAlwaysOnTop(!isAlwaysOnTop()); +} + +bool TaskGroup::isAlwaysOnTop() const +{ + foreach (AbstractItemPtr item, d->members) { + if (!item->isAlwaysOnTop()) { + return false; + } + } + return true; +} + + +bool TaskGroup::isActionSupported(NET::Action action) const +{ + if (KWindowSystem::allowedActionsSupported()) { + foreach (AbstractItemPtr item, d->members) { + if (!item->isActionSupported(action)) { + return false; + } + } + return true; + } + return false; +} + +void TaskGroup::close() +{ + foreach (AbstractItemPtr item, d->members) { + item->close(); + } +} + +bool TaskGroup::isActive() const +{ + foreach (AbstractItemPtr item, d->members) { + if (item->isActive()) { + return true; + } + } + + return false; +} + +bool TaskGroup::demandsAttention() const +{ + foreach (AbstractItemPtr item, d->members) { + if (item->demandsAttention()) { + return true; + } + } + + return false; +} + +bool TaskGroup::moveItem(int oldIndex, int newIndex) +{ + if ((d->members.count() <= newIndex) || (newIndex < 0) || + (d->members.count() <= oldIndex || oldIndex < 0)) { + kDebug() << "index out of bounds"; + return false; + } + + AbstractItemPtr item = d->members.at(oldIndex); + d->members.move(oldIndex, newIndex); + kDebug() << "new index " << d->members.indexOf(item); + emit itemChanged(item); + return true; +} + +} // TaskManager namespace + +#include "taskgroup.moc" diff --git a/taskmanager/taskgroup.h b/taskmanager/taskgroup.h new file mode 100644 index 000000000..006177d2d --- /dev/null +++ b/taskmanager/taskgroup.h @@ -0,0 +1,136 @@ +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * + ***************************************************************************/ + +#ifndef TASKGROUP_H +#define TASKGROUP_H + +#include + +#include +#include + +namespace TaskManager +{ +class GroupManager; + +/** + * TaskGroup, a container for tasks and subgroups + */ +class TASKMANAGER_EXPORT TaskGroup : public AbstractGroupableItem +{ + Q_OBJECT +public: + TaskGroup(GroupManager *parent, QString name, QColor color); + TaskGroup(GroupManager *parent); + ~TaskGroup(); + + ItemList members() const; + + QIcon icon() const; + void setIcon(const QIcon &icon); + + QColor color() const; + void setColor(const QColor &color); + + QString name() const; + void setName(const QString &newName); + + virtual bool isGroupItem() const { return true; } + bool isRootGroup() const; + + /** only true if item is in this group */ + bool hasDirectMember(AbstractItemPtr item) const; + /** only true if item is in this or any sub group */ + bool hasMember(AbstractItemPtr item) const; + /** Returns Direct Member group if the passed item is in a subgroup */ + AbstractItemPtr directMember(AbstractItemPtr) const; + + int desktop() const; + bool isShaded() const; + bool isMaximized() const; + bool isMinimized() const; + bool isFullScreen() const; + bool isKeptBelowOthers() const; + bool isAlwaysOnTop() const; + bool isActionSupported(NET::Action) const; + /** returns true if at least one member is active */ + bool isActive() const; + /** returns true if at least one member is demands attention */ + bool demandsAttention() const; + bool isOnAllDesktops() const; + bool isOnCurrentDesktop() const; + + /** + * Sorting strategies may use this to move items around + * @param oldIndex the index the item to be moved is currently at + * @param newIndex the index the item will be moved to + */ + bool moveItem(int oldIndex, int newIndex); + +public Q_SLOTS: + /** the following are functions which perform the corresponding actions on all member tasks */ + void toDesktop(int); + + void setShaded(bool); + void toggleShaded(); + + void setMaximized(bool); + void toggleMaximized(); + + void setMinimized(bool); + void toggleMinimized(); + + void setFullScreen(bool); + void toggleFullScreen(); + + void setKeptBelowOthers(bool); + void toggleKeptBelowOthers(); + + void setAlwaysOnTop(bool); + void toggleAlwaysOnTop(); + + /** close all members of this group */ + void close(); + + /** add item to group */ + void add(AbstractItemPtr); + + /** remove item from group */ + void remove(AbstractItemPtr); + + /** Removes all tasks and groups from this group */ + void clear(); + +Q_SIGNALS: + /** inform visualization about wat is added and removed */ + void itemAdded(const AbstractItemPtr item); + void itemRemoved(const AbstractItemPtr item); + void groupEditRequest(); + void itemChanged(AbstractItemPtr item); + /** The group changed the desktop, is emitted in the toDesktop function */ + void movedToDesktop(int newDesk); + +private: + class Private; + Private * const d; +}; + + +} // TaskManager namespace + +#endif diff --git a/taskmanager/taskitem.cpp b/taskmanager/taskitem.cpp new file mode 100644 index 000000000..fcae3aac8 --- /dev/null +++ b/taskmanager/taskitem.cpp @@ -0,0 +1,328 @@ +/***************************************************************** + +Copyright 2008 Christian Mollekopf + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************/ + +// Own +#include "taskitem.h" +#include + + +namespace TaskManager +{ + + +class TaskItem::Private +{ +public: + Private() + :task(0), + startupTask(0) + { + } + + TaskPtr task; + StartupPtr startupTask; +}; + + +TaskItem::TaskItem(QObject *parent,TaskPtr task) +: AbstractGroupableItem(parent), + d(new Private) +{ + d->task = task; + connect(task.data(), SIGNAL(changed(::TaskManager::TaskChanges)), + this, SIGNAL(changed(::TaskManager::TaskChanges))); + connect(task.data(), SIGNAL(destroyed()), this, SLOT(deleteLater())); //this item isn't useful anymore if the Task was closed +} + + +TaskItem::TaskItem(QObject *parent, StartupPtr task) +: AbstractGroupableItem(parent), + d(new Private) +{ + d->startupTask = task; + connect(task.data(), SIGNAL(changed(::TaskManager::TaskChanges)), this, SIGNAL(changed(::TaskManager::TaskChanges))); + connect(task.data(), SIGNAL(destroyed()), this, SLOT(deleteLater())); //this item isn't useful anymore if the Task was closed +} + +TaskItem::~TaskItem() +{ + //kDebug(); + /* if (parentGroup()){ + parentGroup()->remove(this); + }*/ + delete d; +} + +void TaskItem::setTaskPointer(TaskPtr task) +{ + if (d->startupTask) { + disconnect(d->startupTask.data(), 0, 0, 0); + d->startupTask = 0; + } + d->task = task; + connect(task.data(), SIGNAL(changed(::TaskManager::TaskChanges)), + this, SIGNAL(changed(::TaskManager::TaskChanges))); + connect(task.data(), SIGNAL(destroyed()), this, SLOT(deleteLater())); + emit gotTaskPointer(); +} + +TaskPtr TaskItem::task() const +{ + if (d->task.isNull()) { + kDebug() << "pointer is Null"; + } + return d->task; +} + +StartupPtr TaskItem::startup() const +{ + if (d->startupTask.isNull()) { + kDebug() << "pointer is Null"; + } + return d->startupTask; +} + +QIcon TaskItem::icon() const +{ + if (!d->task) { + return QIcon(); + } + return d->task->icon(); +} + +QString TaskItem::name() const +{ + if (!d->task) { + return QString(); + } + return d->task->visibleName(); +} + +void TaskItem::setShaded(bool state) +{ + if (!d->task) { + return; + } + d->task->setShaded(state); +} + +void TaskItem::toggleShaded() +{ + if (!d->task) { + return; + } + d->task->toggleShaded(); +} + +bool TaskItem::isShaded() const +{ + if (!d->task) { + return false; + } + return d->task->isShaded(); +} + +void TaskItem::toDesktop(int desk) +{ + if (!d->task) { + return; + } + d->task->toDesktop(desk); +} + +bool TaskItem::isOnCurrentDesktop() const +{ + return d->task && d->task->isOnCurrentDesktop(); +} + +bool TaskItem::isOnAllDesktops() const +{ + return d->task && d->task->isOnAllDesktops(); +} + +int TaskItem::desktop() const +{ + if (!d->task) { + return 0; + } + return d->task->desktop(); +} + +void TaskItem::setMaximized(bool state) +{ + if (!d->task) { + return; + } + d->task->setMaximized(state); +} + +void TaskItem::toggleMaximized() +{ + if (!d->task) { + return; + } + d->task->toggleMaximized(); +} + +bool TaskItem::isMaximized() const +{ + return d->task && d->task->isMaximized(); +} + +void TaskItem::setMinimized(bool state) +{ + if (!d->task) { + return; + } + d->task->setIconified(state); +} + +void TaskItem::toggleMinimized() +{ + if (!d->task) { + return; + } + d->task->toggleIconified(); +} + +bool TaskItem::isMinimized() const +{ + if (!d->task) { + return false; + } + return d->task->isMinimized(); +} + +void TaskItem::setFullScreen(bool state) +{ + if (!d->task) { + return; + } + d->task->setFullScreen(state); +} + +void TaskItem::toggleFullScreen() +{ + if (!d->task) { + return; + } + d->task->toggleFullScreen(); +} + +bool TaskItem::isFullScreen() const +{ + if (!d->task) { + return false; + } + return d->task->isFullScreen(); +} + +void TaskItem::setKeptBelowOthers(bool state) +{ + if (!d->task) { + return; + } + d->task->setKeptBelowOthers(state); +} + +void TaskItem::toggleKeptBelowOthers() +{ + if (!d->task) { + return; + } + d->task->toggleKeptBelowOthers(); +} + +bool TaskItem::isKeptBelowOthers() const +{ + if (!d->task) { + return false; + } + return d->task->isKeptBelowOthers(); +} + +void TaskItem::setAlwaysOnTop(bool state) +{ + if (!d->task) { + return; + } + d->task->setAlwaysOnTop(state); +} + +void TaskItem::toggleAlwaysOnTop() +{ + if (!d->task) { + return; + } + d->task->toggleAlwaysOnTop(); +} + +bool TaskItem::isAlwaysOnTop() const +{ + if (!d->task) { + return false; + } + return d->task->isAlwaysOnTop(); +} + +bool TaskItem::isActionSupported(NET::Action action) const +{ + if (!d->task) { + return false; + } + + if (KWindowSystem::allowedActionsSupported()) { + return (d->task->info().actionSupported(action)); + } + + return false; + //return (!KWindowSystem::allowedActionsSupported() || d->task->info().isActionSupported(action)); +} + +void TaskItem::close() +{ + if (!d->task) { + return; + } + d->task->close(); +} + +bool TaskItem::isActive() const +{ + if (!d->task) { + return false; + } + return d->task->isActive(); +} + +bool TaskItem::demandsAttention() const +{ + if (!d->task) { + return false; + } + return d->task->demandsAttention(); +} + +} // TaskManager namespace + +#include "taskitem.moc" diff --git a/taskmanager/taskitem.h b/taskmanager/taskitem.h new file mode 100644 index 000000000..72918a70c --- /dev/null +++ b/taskmanager/taskitem.h @@ -0,0 +1,103 @@ +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * + ***************************************************************************/ + +#ifndef TASKITEM_H +#define TASKITEM_H + +#include +#include +#include +#include + +#include + +namespace TaskManager +{ + + +/** + * Wrapper class so we do not have to use the Task class directly and the TaskPtr remains guarded + */ +class TASKMANAGER_EXPORT TaskItem : public AbstractGroupableItem +{ + Q_OBJECT +public: + /** Creates a taskitem for a task*/ + TaskItem(QObject *parent, TaskPtr item); + /** Creates a taskitem for a startuptask*/ + TaskItem(QObject *parent, StartupPtr item); + ~TaskItem(); + /** Sets the taskpointer after the startup pointer */ + void setTaskPointer(TaskPtr); + /** Returns the shared pointer to the Task */ + TaskPtr task() const; + + StartupPtr startup() const; + bool isGroupItem() const { return false; } + + QIcon icon() const; + QString name() const; + + bool isOnCurrentDesktop() const; + bool isOnAllDesktops() const; + int desktop() const; + bool isShaded() const; + bool isMaximized() const; + bool isMinimized() const; + bool isFullScreen() const; + bool isKeptBelowOthers() const; + bool isAlwaysOnTop() const; + bool isActive() const; + bool demandsAttention() const; + bool isActionSupported(NET::Action) const; + +public Q_SLOTS: + void toDesktop(int); + + void setShaded(bool); + void toggleShaded(); + + void setMaximized(bool); + void toggleMaximized(); + + void setMinimized(bool); + void toggleMinimized(); + + void setFullScreen(bool); + void toggleFullScreen(); + + void setKeptBelowOthers(bool); + void toggleKeptBelowOthers(); + + void setAlwaysOnTop(bool); + void toggleAlwaysOnTop(); + + void close(); + +Q_SIGNALS: + /** Indicates that the startup task now is a normal task */ + void gotTaskPointer(); + +private: + class Private; + Private * const d; +}; + +} // TaskManager namespace + +#endif diff --git a/taskmanager/taskmanager.cpp b/taskmanager/taskmanager.cpp new file mode 100644 index 000000000..dc9ab5eeb --- /dev/null +++ b/taskmanager/taskmanager.cpp @@ -0,0 +1,535 @@ +/***************************************************************** + +Copyright (c) 2000 Matthias Elter + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************/ + +// Own +#include "taskmanager.h" +#include "taskmanager_p.h" + +// KDE +#include +#include +#include +#include + +#ifdef Q_WS_X11 +#include +#endif +#include +#include + +namespace TaskManager +{ + +class TaskManagerSingleton +{ +public: + TaskManager self; +}; + +K_GLOBAL_STATIC( TaskManagerSingleton, privateTaskManagerSelf ) + +TaskManager* TaskManager::self() +{ + return &privateTaskManagerSelf->self; +} + +class TaskManager::Private +{ +public: + Private() + : active(0), + startupInfo(0), + trackGeometry(false) + { + } + + TaskPtr active; + KStartupInfo* startupInfo; + TaskDict tasksByWId; + StartupList startups; + WindowList skiptaskbarWindows; + bool trackGeometry; +}; + +TaskManager::TaskManager() + : QObject(), + d(new Private) +{ + KGlobal::locale()->insertCatalog("libtaskmanager"); + connect(KWindowSystem::self(), SIGNAL(windowAdded(WId)), + this, SLOT(windowAdded(WId))); + connect(KWindowSystem::self(), SIGNAL(windowRemoved(WId)), + this, SLOT(windowRemoved(WId))); + connect(KWindowSystem::self(), SIGNAL(activeWindowChanged(WId)), + this, SLOT(activeWindowChanged(WId))); + connect(KWindowSystem::self(), SIGNAL(currentDesktopChanged(int)), + this, SLOT(currentDesktopChanged(int))); + connect(KWindowSystem::self(), SIGNAL(windowChanged(WId,unsigned int)), + this, SLOT(windowChanged(WId,unsigned int))); + + // register existing windows + const QList windows = KWindowSystem::windows(); + QList::ConstIterator end(windows.end()); + for (QList::ConstIterator it = windows.begin(); it != end; ++it) + { + windowAdded(*it); + } + + // set active window + WId win = KWindowSystem::activeWindow(); + activeWindowChanged(win); + configure_startup(); +} + +TaskManager::~TaskManager() +{ + KGlobal::locale()->removeCatalog("libtaskmanager"); + delete d; +} + +void TaskManager::configure_startup() +{ + KConfig _c( "klaunchrc" ); + KConfigGroup c(&_c, "FeedbackStyle"); + if (!c.readEntry("TaskbarButton", true)) + return; + d->startupInfo = new KStartupInfo( KStartupInfo::CleanOnCantDetect, this ); + connect( d->startupInfo, + SIGNAL( gotNewStartup( const KStartupInfoId&, const KStartupInfoData& )), + SLOT( gotNewStartup( const KStartupInfoId&, const KStartupInfoData& ))); + connect( d->startupInfo, + SIGNAL( gotStartupChange( const KStartupInfoId&, const KStartupInfoData& )), + SLOT( gotStartupChange( const KStartupInfoId&, const KStartupInfoData& ))); + connect( d->startupInfo, + SIGNAL( gotRemoveStartup( const KStartupInfoId&, const KStartupInfoData& )), + SLOT( killStartup( const KStartupInfoId& ))); + c=KConfigGroup(&_c, "TaskbarButtonSettings"); + d->startupInfo->setTimeout( c.readEntry( "Timeout", 30 )); +} + +TaskPtr TaskManager::findTask(WId w) +{ + // TODO: might be able to be made more efficient if + // we check to see if w is a transient first? + // profiling would say whether this is worth the effort + + TaskDict::iterator it = d->tasksByWId.begin(); + TaskDict::iterator itEnd = d->tasksByWId.end(); + + for (; it != itEnd; ++it) + { + if (it.key() == w || it.value()->hasTransient(w)) + { + return it.value(); + } + } + + return TaskPtr(); +} + +TaskPtr TaskManager::findTask(int desktop, const QPoint& p) +{ + QList list = KWindowSystem::stackingOrder(); + + TaskPtr task; + int currentIndex = -1; + TaskDict::iterator itEnd = d->tasksByWId.end(); + for (TaskDict::iterator it = d->tasksByWId.begin(); it != itEnd; ++it) + { + TaskPtr t = it.value(); + if (!t->isOnAllDesktops() && t->desktop() != desktop) + { + continue; + } + + if (t->isIconified() || t->isShaded()) + { + continue; + } + + if (t->geometry().contains(p)) + { + int index = list.indexOf(t->window()); + if (index > currentIndex) + { + currentIndex = index; + task = t; + } + } + } + + return task; +} + +void TaskManager::windowAdded(WId w ) +{ + NETWinInfo info(QX11Info::display(), w, QX11Info::appRootWindow(), + NET::WMWindowType | NET::WMPid | NET::WMState); + + // ignore NET::Tool and other special window types + NET::WindowType wType = + info.windowType( NET::NormalMask | NET::DesktopMask | NET::DockMask | + NET::ToolbarMask | NET::MenuMask | NET::DialogMask | + NET::OverrideMask | NET::TopMenuMask | + NET::UtilityMask | NET::SplashMask ); + + if (wType != NET::Normal && + wType != NET::Override && + wType != NET::Unknown && + wType != NET::Dialog && + wType != NET::Utility) + { + return; + } + + // ignore windows that want to be ignored by the taskbar + if ((info.state() & NET::SkipTaskbar) != 0) + { + d->skiptaskbarWindows.push_front( w ); // remember them though + return; + } + + Window transient_for_tmp; + if (XGetTransientForHint( QX11Info::display(), (Window) w, &transient_for_tmp )) + { + WId transient_for = (WId) transient_for_tmp; + + // check if it's transient for a skiptaskbar window + if( d->skiptaskbarWindows.contains( transient_for )) + return; + + // lets see if this is a transient for an existing task + if( transient_for != QX11Info::appRootWindow() + && transient_for != 0 + && wType != NET::Utility ) + { + TaskPtr t = findTask(transient_for); + if (t) + { + if (t->window() != w) + { + t->addTransient(w, info); + // kDebug() << "TM: Transient " << w << " added for Task: " << t->window(); + } + return; + } + } + } + + TaskPtr t( new Task( w, 0 ) ); + d->tasksByWId[w] = t; + + if (d->startupInfo) { + KStartupInfoId startupInfoId; + // checkStartup modifies startupInfoId + d->startupInfo->checkStartup(w, startupInfoId); + foreach (StartupPtr startup, d->startups) { + if (startup->id() == startupInfoId) { + startup->addWindowMatch(w); + } + } + } + + // kDebug() << "TM: Task added for WId: " << w; + + emit taskAdded(t); +} + +void TaskManager::windowRemoved(WId w) +{ + d->skiptaskbarWindows.removeAll(w); + + // find task + TaskPtr t = findTask(w); + if (!t) + { + return; + } + + if (t->window() == w) + { + d->tasksByWId.remove(w); + emit taskRemoved(t); + + if (t == d->active) + { + d->active = 0; + } + + //kDebug() << "TM: Task for WId " << w << " removed."; + } + else + { + t->removeTransient(w); + //kDebug() << "TM: Transient " << w << " for Task " << t->window() << " removed."; + } +} + +void TaskManager::windowChanged(WId w, unsigned int dirty) +{ + if (dirty & NET::WMState) { + NETWinInfo info (QX11Info::display(), w, QX11Info::appRootWindow(), + NET::WMState | NET::XAWMState); + + if (info.state() & NET::SkipTaskbar) { + windowRemoved(w); + d->skiptaskbarWindows.push_front(w); + return; + } else { + d->skiptaskbarWindows.removeAll(w); + if (info.mappingState() != NET::Withdrawn && !findTask(w)) { + // skipTaskBar state was removed and the window is still + // mapped, so add this window + windowAdded( w ); + } + } + } + + // check if any state we are interested in is marked dirty + if (!(dirty & (NET::WMVisibleName |NET::WMName | + NET::WMState | NET::WMIcon | + NET::XAWMState | NET::WMDesktop) || + (d->trackGeometry && dirty & NET::WMGeometry))) { + return; + } + + // find task + TaskPtr t = findTask(w); + if (!t) { + return; + } + + //kDebug() << "TaskManager::windowChanged " << w << " " << dirty; + + if (dirty & NET::WMState) { + t->updateDemandsAttentionState(w); + } + + // refresh icon pixmap if necessary + if (dirty & NET::WMIcon) { + //TODO should we forward on icon changes, too? + t->refreshIcon(); + dirty ^= NET::WMIcon; + } + + TaskChanges changes = TaskUnchanged; + + //kDebug() << "got changes, but will we refresh?" << dirty; + if (dirty) { + // only refresh this stuff if we have other changes besides icons + changes = t->refresh(dirty); + } + + if (changes != TaskUnchanged) { + emit windowChanged(t, changes); + } +} + +void TaskManager::updateWindowPixmap(WId w) +{ + if (!KWindowSystem::compositingActive()) + { + return; + } + + TaskPtr task = findTask(w); + if (task) + { + task->updateWindowPixmap(); + } +} + +void TaskManager::activeWindowChanged(WId w ) +{ + //kDebug() << "TaskManager::activeWindowChanged"; + + TaskPtr t = findTask( w ); + if (!t) { + if (d->active) { + d->active->setActive(false); + d->active = 0; + } + } + else { + if (d->active) + d->active->setActive(false); + + d->active = t; + d->active->setActive(true); + } +} + +void TaskManager::currentDesktopChanged(int desktop) +{ + emit desktopChanged(desktop); +} + +void TaskManager::gotNewStartup( const KStartupInfoId& id, const KStartupInfoData& data ) +{ + StartupPtr s( new Startup( id, data, 0 ) ); + d->startups.append(s); + + emit startupAdded(s); +} + +void TaskManager::gotStartupChange( const KStartupInfoId& id, const KStartupInfoData& data ) +{ + StartupList::iterator itEnd = d->startups.end(); + for (StartupList::iterator sIt = d->startups.begin(); sIt != itEnd; ++sIt) + { + if ((*sIt)->id() == id) + { + (*sIt)->update(data); + return; + } + } +} + +void TaskManager::killStartup( const KStartupInfoId& id ) +{ + StartupList::iterator sIt = d->startups.begin(); + StartupList::iterator itEnd = d->startups.end(); + StartupPtr s; + for (; sIt != itEnd; ++sIt) + { + if ((*sIt)->id() == id) + { + s = *sIt; + break; + } + } + + if (!s) + { + return; + } + + d->startups.erase(sIt); + emit startupRemoved(s); +} + +void TaskManager::killStartup(StartupPtr s) +{ + if (!s) + { + return; + } + + StartupList::iterator sIt = d->startups.begin(); + StartupList::iterator itEnd = d->startups.end(); + for (; sIt != itEnd; ++sIt) + { + if ((*sIt) == s) + { + d->startups.erase(sIt); + break; + } + } + + emit startupRemoved(s); +} + +QString TaskManager::desktopName(int desk) const +{ + return KWindowSystem::desktopName(desk); +} + +TaskDict TaskManager::tasks() const +{ + return d->tasksByWId; +} + +StartupList TaskManager::startups() const +{ + return d->startups; +} + +int TaskManager::numberOfDesktops() const +{ + return KWindowSystem::numberOfDesktops(); +} + +bool TaskManager::isOnTop(const Task* task) +{ + if (!task) + { + return false; + } + + QList list = KWindowSystem::stackingOrder(); + QList::const_iterator begin(list.constBegin()); + QList::const_iterator it = list.begin() + (list.size() - 1); + do + { + TaskDict::iterator taskItEnd = d->tasksByWId.end(); + for (TaskDict::iterator taskIt = d->tasksByWId.begin(); + taskIt != taskItEnd; ++taskIt) + { + TaskPtr t = taskIt.value(); + if ((*it) == t->window()) + { + if (t == task) + { + return true; + } + + if (!t->isIconified() && + (t->isAlwaysOnTop() == task->isAlwaysOnTop())) + { + return false; + } + + break; + } + } + } while (it-- != begin); + + return false; +} + +void TaskManager::trackGeometry(bool state) +{ + d->trackGeometry = state; +} + +bool TaskManager::isOnScreen(int screen, const WId wid) +{ + if (screen == -1) + { + return true; + } + + KWindowInfo wi = KWindowSystem::windowInfo(wid, NET::WMFrameExtents); + + // for window decos that fudge a bit and claim to extend beyond the + // edge of the screen, we just contract a bit. + QRect window = wi.frameGeometry(); + QRect desktop = QApplication::desktop()->screenGeometry(screen); + desktop.adjust(5, 5, -5, -5); + return window.intersects(desktop); +} + +} // TaskManager namespace + + +#include "taskmanager.moc" diff --git a/taskmanager/taskmanager.h b/taskmanager/taskmanager.h new file mode 100644 index 000000000..3235defb4 --- /dev/null +++ b/taskmanager/taskmanager.h @@ -0,0 +1,206 @@ +/***************************************************************** + +Copyright (c) 2000-2001 Matthias Elter +Copyright (c) 2001 Richard Moore + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************/ + +#ifndef TASKMANAGER_H +#define TASKMANAGER_H + +#include +#include + +#include +#include + +namespace TaskManager +{ +typedef QList WindowList; + +class Task; +typedef KSharedPtr TaskPtr; +typedef QVector TaskList; +typedef QHash TaskDict; + +enum TaskChange { TaskUnchanged = 0, + NameChanged = 1, + StateChanged = 2, + DesktopChanged = 32, + GeometryChanged = 64, + WindowTypeChanged = 128, + ActionsChanged = 256, + TransientsChanged = 512, + IconChanged = 1024, + ColorChanged = 2048, + EverythingChanged = 0xffff + }; +Q_DECLARE_FLAGS(TaskChanges, TaskChange) +} // namespace TaskManager + +// Own +#include +#include +#include + +namespace TaskManager +{ + +/** + * A generic API for task managers. This class provides an easy way to + * build NET compliant task managers. It provides support for startup + * notification, virtual desktops and the full range of WM properties. + * + * @see Task + * @see Startup + */ +class TASKMANAGER_EXPORT TaskManager : public QObject +{ + Q_OBJECT + Q_PROPERTY( int currentDesktop READ currentDesktop ) + Q_PROPERTY( int numberOfDesktops READ numberOfDesktops ) + +public: + static TaskManager* self(); + + TaskManager(); + ~TaskManager(); + + /** + * Returns the task for a given WId, or 0 if there is no such task. + */ + TaskPtr findTask(WId w); + + /** + * Returns the task for a given location, or 0 if there is no such task. + */ + TaskPtr findTask(int desktop, const QPoint& p); + + /** + * Returns a list of all current tasks. + */ + TaskDict tasks() const; + + /** + * Returns a list of all current startups. + */ + StartupList startups() const; + + /** + * Returns the name of the nth desktop. + */ + QString desktopName(int n) const; + + /** + * Returns the number of virtual desktops. + */ + int numberOfDesktops() const; + + /** + * Returns the number of the current desktop. + */ + int currentDesktop() const; + + /** + * Returns true if the specified task is on top. + */ + bool isOnTop(const Task*); + + /** + * Tells the task manager whether or not we care about geometry + * updates. This generates a lot of activity so should only be used + * when necessary. + */ + void trackGeometry(bool); + + /** + * Returns whether the Window with WId wid is on the screen screen + */ + static bool isOnScreen( int screen, const WId wid ); + +Q_SIGNALS: + /** + * Emitted when a new task has started. + */ + void taskAdded(TaskPtr); + + /** + * Emitted when a task has terminated. + */ + void taskRemoved(TaskPtr); + + /** + * Emitted when a new task is expected. + */ + void startupAdded(StartupPtr); + + /** + * Emitted when a startup item should be removed. This could be because + * the task has started, because it is known to have died, or simply + * as a result of a timeout. + */ + void startupRemoved(StartupPtr); + + /** + * Emitted when the current desktop changes. + */ + void desktopChanged(int desktop); + + /** + * Emitted when a window changes desktop. + */ + void windowChanged(TaskPtr task, ::TaskManager::TaskChanges change); + +protected Q_SLOTS: + //* @internal + void windowAdded(WId); + //* @internal + void windowRemoved(WId); + //* @internal + void windowChanged(WId, unsigned int); + + //* @internal + void activeWindowChanged(WId); + //* @internal + void currentDesktopChanged(int); + //* @internal + void killStartup( const KStartupInfoId& ); + //* @internal + void killStartup(StartupPtr); + + //* @internal + void gotNewStartup( const KStartupInfoId&, const KStartupInfoData& ); + //* @internal + void gotStartupChange( const KStartupInfoId&, const KStartupInfoData& ); + +protected: + void configure_startup(); + void updateWindowPixmap(WId); + +private: + class Private; + Private * const d; +}; + +} // TaskManager namespace + +Q_DECLARE_OPERATORS_FOR_FLAGS(TaskManager::TaskChanges) + +#endif diff --git a/taskmanager/taskmanager_export.h b/taskmanager/taskmanager_export.h new file mode 100644 index 000000000..d87a57309 --- /dev/null +++ b/taskmanager/taskmanager_export.h @@ -0,0 +1,45 @@ +/***************************************************************** + +Copyright 2008 Aaron Seigo + +#ifndef TASKMANAGER_EXPORT +# if defined(MAKE_TASKMANAGER_LIB) + /* We are building this library */ +# define TASKMANAGER_EXPORT KDE_EXPORT +# else + /* We are using this library */ +# define TASKMANAGER_EXPORT KDE_IMPORT +# endif +#endif + +# ifndef TASKMANAGER_EXPORT_DEPRECATED +# define TASKMANAGER_EXPORT_DEPRECATED KDE_DEPRECATED TASKMANAGER_EXPORT +# endif + +#endif diff --git a/taskmanager/taskmanager_p.h b/taskmanager/taskmanager_p.h new file mode 100644 index 000000000..0ba109c56 --- /dev/null +++ b/taskmanager/taskmanager_p.h @@ -0,0 +1,51 @@ +/***************************************************************** + +Copyright (c) 2000-2001 Matthias Elter +Copyright (c) 2001 Richard Moore + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************/ + +#ifndef TASKMANAGER_P_H +#define TASKMANAGER_P_H + +//Qt includes +#ifdef Q_WS_X11 + + +#include "config-X11.h" + +#if defined(HAVE_XCOMPOSITE) && \ + defined(HAVE_XRENDER) && \ + defined(HAVE_XFIXES) +#include +#include +#include +#include +#include +#if XCOMPOSITE_VERSION >= 00200 && \ + XFIXES_VERSION >= 20000 && \ + (RENDER_MAJOR > 0 || RENDER_MINOR >= 6) +#define THUMBNAILING_POSSIBLE +#endif +#endif + +#endif + +#endif //TASKMANAGER_P_H diff --git a/taskmanager/taskrmbmenu.cpp b/taskmanager/taskrmbmenu.cpp new file mode 100644 index 000000000..fc65acc79 --- /dev/null +++ b/taskmanager/taskrmbmenu.cpp @@ -0,0 +1,363 @@ +/***************************************************************** + +Copyright (c) 2001 Matthias Elter +Copyright (c) 2001 John Firebaugh + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************/ + +// Own +#include "taskmanager.h" + +// System +#include + +// KDE +#include +#include + +#include "config-X11.h" + +#if defined(HAVE_XCOMPOSITE) && \ + defined(HAVE_XRENDER) && \ + defined(HAVE_XFIXES) +#include +#endif + +#include "taskrmbmenu.h" + +static const int ALL_DESKTOPS = 0; + +namespace TaskManager +{ + +TaskRMBMenu::TaskRMBMenu(const TaskList& theTasks, bool show, QWidget *parent) + : QMenu( parent ) + , tasks( theTasks ) + , showAll( show ) +{ + assert(tasks.count() > 0); + if (tasks.count() == 1) + { + fillMenu(tasks.first()); + } + else + { + fillMenu(); + } +} + +TaskRMBMenu::TaskRMBMenu(TaskPtr task, bool show, QWidget *parent) + : QMenu( parent ) + , showAll( show ) +{ + fillMenu(task); +} + +void TaskRMBMenu::fillMenu(TaskPtr t) +{ + QAction *a; + + addMenu(makeAdvancedMenu(t)); + bool checkActions = KWindowSystem::allowedActionsSupported(); + + if (TaskManager::self()->numberOfDesktops() > 1) + { + a = addMenu(makeDesktopsMenu(t)); + + if (showAll) + { + a = addAction(i18n("&To Current Desktop"), + t.data(), SLOT(toCurrentDesktop())); + a->setEnabled(!t->isOnCurrentDesktop()); + } + + if (checkActions) + { + a->setEnabled(t->info().actionSupported(NET::ActionChangeDesktop)); + } + } + + a = addAction(KIcon("transform-move"), i18n("&Move"), t.data(), SLOT(move())); + a->setEnabled(!checkActions || t->info().actionSupported(NET::ActionMove)); + + a = addAction(i18n("Re&size"), t.data(), SLOT(resize())); + a->setEnabled(!checkActions || t->info().actionSupported(NET::ActionResize)); + + a = addAction(i18n("Mi&nimize"), t.data(), SLOT(toggleIconified())); + a->setCheckable(true); + a->setChecked(t->isIconified()); + a->setEnabled(!checkActions || t->info().actionSupported(NET::ActionMinimize)); + + a = addAction(i18n("Ma&ximize"), t.data(), SLOT(toggleMaximized())); + a->setCheckable(true); + a->setChecked(t->isMaximized()); + a->setEnabled(!checkActions || t->info().actionSupported(NET::ActionMax)); + + a = addAction(i18n("&Shade"), t.data(), SLOT(toggleShaded())); + a->setCheckable(true); + a->setChecked(t->isShaded()); + a->setEnabled(!checkActions || t->info().actionSupported(NET::ActionShade)); + + addSeparator(); + + a = addAction(KIcon("window-close"), i18n("&Close"), t.data(), SLOT(close())); + a->setEnabled(!checkActions || t->info().actionSupported(NET::ActionClose)); +} + +void TaskRMBMenu::fillMenu() +{ + QAction *a; + + TaskList::iterator itEnd = tasks.end(); + for (TaskList::iterator it = tasks.begin(); it != itEnd; ++it) + { + TaskPtr t = (*it); + + a = addMenu( new TaskRMBMenu(t, this) ); + a->setIcon( QIcon( t->pixmap() ) ); + a->setText( t->visibleNameWithState() ); + a->setChecked(t->isActive()); + connect( a, SIGNAL(triggered()), t.data(), SLOT( activateRaiseOrIconify() ) ); + } + + addSeparator(); + + bool enable = false; + + if (TaskManager::self()->numberOfDesktops() > 1) + { + a = addMenu(makeDesktopsMenu()); + + a = addAction(i18n("All &to Current Desktop"), this, SLOT(slotAllToCurrentDesktop())); + TaskList::iterator itEnd = tasks.end(); + for (TaskList::iterator it = tasks.begin(); it != itEnd; ++it) + { + if (!(*it)->isOnCurrentDesktop()) + { + enable = true; + break; + } + } + a->setEnabled(enable); + } + + enable = false; + + a = addAction( i18n( "Mi&nimize All" ), this, SLOT( slotMinimizeAll() ) ); + itEnd = tasks.end(); + for (TaskList::iterator it = tasks.begin(); it != itEnd; ++it) + { + if( !(*it)->isIconified() ) { + enable = true; + break; + } + } + a->setEnabled( enable ); + + enable = false; + + a = addAction( i18n( "Ma&ximize All" ), this, SLOT( slotMaximizeAll() ) ); + itEnd = tasks.end(); + for (TaskList::iterator it = tasks.begin(); it != itEnd; ++it) + { + if( !(*it)->isMaximized() ) { + enable = true; + break; + } + } + a->setEnabled( enable ); + + enable = false; + + a = addAction( i18n( "&Restore All" ), this, SLOT( slotRestoreAll() ) ); + itEnd = tasks.end(); + for (TaskList::iterator it = tasks.begin(); it != itEnd; ++it) + { + if( (*it)->isIconified() || (*it)->isMaximized() ) { + enable = true; + break; + } + } + a->setEnabled( enable ); + + addSeparator(); + + enable = false; + + addAction( KIcon( "list-remove" ), i18n( "&Close All" ), this, SLOT( slotCloseAll() ) ); +} + +QMenu* TaskRMBMenu::makeAdvancedMenu(TaskPtr t) +{ + QAction *a; + QMenu* menu = new QMenu(this); + menu->setTitle(i18n("Ad&vanced")); + + a = menu->addAction(KIcon("go-up"), + i18n("Keep &Above Others"), + t.data(), SLOT(toggleAlwaysOnTop())); + a->setCheckable(true); + a->setChecked(t->isAlwaysOnTop()); + + a = menu->addAction(KIcon("go-down"), + i18n("Keep &Below Others"), + t.data(), SLOT(toggleKeptBelowOthers())); + a->setCheckable(true); + a->setChecked(t->isKeptBelowOthers()); + + a = menu->addAction(KIcon("view-fullscreen"), + i18n("&Fullscreen"), + t.data(), SLOT(toggleFullScreen())); + a->setCheckable(true); + a->setChecked(t->isFullScreen()); + + if (KWindowSystem::allowedActionsSupported()) + { + a->setEnabled(t->info().actionSupported(NET::ActionFullScreen)); + } + + return menu; +} + +QMenu* TaskRMBMenu::makeDesktopsMenu(TaskPtr t) +{ + QMenu* m = new QMenu(this); + m->setTitle(i18n("To &Desktop")); + + QAction *a = m->addAction(i18n("&All Desktops"), this, SLOT(slotToDesktop())); + a->setCheckable(true); + toDesktopMap.append(QPair(t, ALL_DESKTOPS)); + a->setData(ALL_DESKTOPS); + a->setChecked(t->isOnAllDesktops()); + + m->addSeparator(); + + for (int i = 1; i <= TaskManager::self()->numberOfDesktops(); i++) { + QString name = QString("&%1 %2").arg(i).arg(TaskManager::self()->desktopName(i).replace('&', "&&")); + a = m->addAction( name, this, SLOT( slotToDesktop() ) ); + a->setCheckable(true); + toDesktopMap.append( QPair( t, i ) ); + a->setData( i ); + a->setChecked( !t->isOnAllDesktops() && t->desktop() == i ); + } + + return m; +} + +QMenu* TaskRMBMenu::makeDesktopsMenu() +{ + QMenu* m = new QMenu(this); + m->setTitle(i18n("All to &Desktop")); + QAction *a; + + a = m->addAction(i18n("&All Desktops"), this, SLOT(slotAllToDesktop())); + a->setData(ALL_DESKTOPS); + + m->addSeparator(); + + for (int i = 1; i <= TaskManager::self()->numberOfDesktops(); i++) { + QString name = QString("&%1 %2").arg(i).arg(TaskManager::self()->desktopName(i).replace('&', "&&")); + a = m->addAction(name, this, SLOT(slotAllToDesktop())); + a->setData(i); + } + + return m; +} + +void TaskRMBMenu::slotMinimizeAll() +{ + TaskList::iterator itEnd = tasks.end(); + for (TaskList::iterator it = tasks.begin(); it != itEnd; ++it) + { + (*it)->setIconified(true); + } +} + +void TaskRMBMenu::slotMaximizeAll() +{ + TaskList::iterator itEnd = tasks.end(); + for (TaskList::iterator it = tasks.begin(); it != itEnd; ++it) + { + (*it)->setMaximized(true); + } +} + +void TaskRMBMenu::slotRestoreAll() +{ + TaskList::iterator itEnd = tasks.end(); + for (TaskList::iterator it = tasks.begin(); it != itEnd; ++it) + { + (*it)->restore(); + } +} + +void TaskRMBMenu::slotShadeAll() +{ + TaskList::iterator itEnd = tasks.end(); + for (TaskList::iterator it = tasks.begin(); it != itEnd; ++it) + { + (*it)->setShaded( !(*it)->isShaded() ); + } +} + +void TaskRMBMenu::slotCloseAll() +{ + TaskList::iterator itEnd = tasks.end(); + for (TaskList::iterator it = tasks.begin(); it != itEnd; ++it) + { + (*it)->close(); + } +} + +void TaskRMBMenu::slotAllToDesktop() +{ + QAction *action = qobject_cast( sender() ); + if( action ) { + int desktop = action->data().toInt(); + TaskList::iterator itEnd = tasks.end(); + for (TaskList::iterator it = tasks.begin(); it != itEnd; ++it) + { + (*it)->toDesktop( desktop ); + } + } +} + +void TaskRMBMenu::slotAllToCurrentDesktop() +{ + TaskList::iterator itEnd = tasks.end(); + for (TaskList::iterator it = tasks.begin(); it != itEnd; ++it) + { + (*it)->toCurrentDesktop(); + } +} + +void TaskRMBMenu::slotToDesktop() +{ + QAction *action = qobject_cast( sender() ); + if( action ) { + QPair pair = toDesktopMap[action->data().toInt()]; + pair.first->toDesktop( pair.second ); + } +} + +} // TaskManager namespace + + +#include "taskrmbmenu.moc" diff --git a/taskmanager/taskrmbmenu.h b/taskmanager/taskrmbmenu.h new file mode 100644 index 000000000..929666c6d --- /dev/null +++ b/taskmanager/taskrmbmenu.h @@ -0,0 +1,74 @@ +/***************************************************************** + +Copyright (c) 2001 Matthias Elter +Copyright (c) 2001 John Firebaugh + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************/ + +#ifndef TASKRMBMENU_H +#define TASKRMBMENU_H + +// Qt +#include +#include +#include + +// Own +#include +#include + +namespace TaskManager +{ + +class TASKMANAGER_EXPORT TaskRMBMenu : public QMenu +{ + Q_OBJECT + +public: + explicit TaskRMBMenu(const TaskList&, bool showAll = true, QWidget *parent = 0); + explicit TaskRMBMenu(TaskPtr, bool showAll = true, QWidget *parent = 0); + +private: + void fillMenu(TaskPtr); + void fillMenu(); + QMenu* makeAdvancedMenu(TaskPtr); + QMenu* makeDesktopsMenu(TaskPtr); + QMenu* makeDesktopsMenu(); + +private Q_SLOTS: + void slotMinimizeAll(); + void slotMaximizeAll(); + void slotRestoreAll(); + void slotShadeAll(); + void slotCloseAll(); + void slotAllToDesktop(); + void slotAllToCurrentDesktop(); + void slotToDesktop(); + +private: + TaskList tasks; + bool showAll; + QList< QPair > toDesktopMap; +}; + +} // TaskManager namespace + + +#endif