├── .github └── workflows │ ├── build.yaml │ ├── documentation.yaml │ └── release.yaml ├── .gitignore ├── .gitmodules ├── LICENSE ├── Makefile ├── README.md ├── examples └── ndb-common.sh ├── ndb-cli ├── README.md ├── go.mod ├── go.sum ├── ndb-cli └── ndb_cli.go ├── qdoc ├── config │ ├── NickelDBus.qdocconf │ ├── compat.qdocconf │ ├── ndb-html-header-online.qdocconf │ └── template │ │ ├── images │ │ ├── arrow.png │ │ ├── arrow_bc.png │ │ ├── arrow_down.png │ │ ├── bg_l.png │ │ ├── bg_l_blank.png │ │ ├── bg_ll_blank.png │ │ ├── bg_r.png │ │ ├── bg_ul_blank.png │ │ ├── bgrContent.png │ │ ├── blu_dot.png │ │ ├── box_bg.png │ │ ├── breadcrumb.png │ │ ├── btn_next.png │ │ ├── btn_prev.png │ │ ├── bullet_dn.png │ │ ├── bullet_gt.png │ │ ├── bullet_sq.png │ │ ├── bullet_up.png │ │ ├── feedbackground.png │ │ ├── header_bg.png │ │ ├── home.png │ │ ├── horBar.png │ │ ├── ico_note.png │ │ ├── ico_note_attention.png │ │ ├── ico_out.png │ │ ├── logo.png │ │ ├── page.png │ │ ├── page_bg.png │ │ └── spinner.gif │ │ └── style │ │ └── online.css └── pages.qdoc ├── res └── com-github-shermp-nickeldbus.conf ├── script └── make-dbus-conf.sh └── src ├── cli ├── .gitignore ├── Makefile ├── ndb_cli.cc ├── ndb_cli.h └── qndb.cc ├── interface ├── com.github.shermp.nickeldbus.xml ├── ndb_adapter.cpp ├── ndb_adapter.h ├── ndb_proxy.cpp └── ndb_proxy.h └── ndb ├── NDBCfmDlg.cc ├── NDBCfmDlg.h ├── NDBDbus.cc ├── NDBDbus.h ├── NDBWidgets.cc ├── NDBWidgets.h ├── ndb.h ├── nickeldbus.cc ├── util.cc └── util.h /.github/workflows/build.yaml: -------------------------------------------------------------------------------- 1 | name: Build 2 | on: [push, pull_request] 3 | 4 | jobs: 5 | build_ndb: 6 | name: ndb 7 | runs-on: ubuntu-latest 8 | container: ghcr.io/pgaskin/nickeltc:1.0 9 | steps: 10 | - name: Checkout 11 | uses: actions/checkout@v4 12 | with: 13 | submodules: recursive 14 | - name: Build 15 | run: make clean && make all cli koboroot 16 | - name: Build Documentation 17 | run: make doc 18 | - name: Upload KoboRoot with 'qndb' 19 | uses: actions/upload-artifact@v4 20 | with: 21 | name: NickelDBus 22 | path: KoboRoot.tgz 23 | - name: Upload documentation 24 | uses: actions/upload-artifact@v4 25 | with: 26 | name: Documentation 27 | path: ./qdoc/html 28 | -------------------------------------------------------------------------------- /.github/workflows/documentation.yaml: -------------------------------------------------------------------------------- 1 | name: Documentation 2 | on: 3 | push: 4 | tags: 5 | - "*" 6 | jobs: 7 | build_doc: 8 | name: ndb_doc 9 | runs-on: ubuntu-latest 10 | container: ghcr.io/pgaskin/nickeltc:1.0 11 | steps: 12 | - name: Checkout 13 | uses: actions/checkout@v4 14 | with: 15 | submodules: recursive 16 | - name: Build 17 | run: make doc 18 | - name: Deploy 19 | uses: peaceiris/actions-gh-pages@v4 20 | with: 21 | github_token: ${{ secrets.GITHUB_TOKEN }} 22 | publish_dir: ./qdoc/html 23 | -------------------------------------------------------------------------------- /.github/workflows/release.yaml: -------------------------------------------------------------------------------- 1 | name: Create Release 2 | on: 3 | push: 4 | tags: 5 | - "*" 6 | jobs: 7 | build_ndb: 8 | name: ndb 9 | runs-on: ubuntu-latest 10 | container: ghcr.io/pgaskin/nickeltc:1.0 11 | steps: 12 | - name: Checkout 13 | uses: actions/checkout@v4 14 | with: 15 | submodules: recursive 16 | - name: Build 17 | run: make clean && make all cli koboroot 18 | - name: Create release 19 | uses: softprops/action-gh-release@v2 20 | with: 21 | draft: true 22 | body: '' 23 | files: | 24 | KoboRoot.tgz 25 | token: ${{ secrets.GITHUB_TOKEN }} 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # make gitignore 2 | src/interface/ndb_proxy.moc 3 | src/interface/ndb_proxy.o 4 | src/interface/ndb_proxy.moc.o 5 | qdoc/html/ 6 | .kdev4/ 7 | *.kdev4 8 | .kateconfig 9 | .vscode/ 10 | .idea/ 11 | .clangd/ 12 | .cache/ 13 | compile_commands.json 14 | /res/ndb_version 15 | /KoboRoot.tgz 16 | /libndb.so 17 | /NickelMenu/src/util.o 18 | /NickelMenu/src/action.o 19 | /NickelMenu/src/action_c.o 20 | /NickelMenu/src/kfmon.o 21 | /src/ndb/nickeldbus.o 22 | /src/ndb/NDBDbus.o 23 | /src/ndb/NDBCfmDlg.o 24 | /src/ndb/NDBWidgets.o 25 | /src/ndb/util.o 26 | /NickelMenu/src/action_cc.o 27 | /src/interface/ndb_adapter.o 28 | /src/ndb/NDBDbus.moc 29 | /src/ndb/NDBCfmDlg.moc 30 | /src/ndb/NDBWidgets.moc 31 | /src/interface/ndb_adapter.moc 32 | /src/ndb/NDBDbus.moc.o 33 | /src/ndb/NDBCfmDlg.moc.o 34 | /src/ndb/NDBWidgets.moc.o 35 | /src/interface/ndb_adapter.moc.o 36 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "NickelMenu"] 2 | path = NickelMenu 3 | url = https://github.com/pgaskin/NickelMenu.git 4 | [submodule "NickelHook"] 5 | path = NickelHook 6 | url = https://github.com/pgaskin/NickelHook.git 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Sherman Perry 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | include NickelHook/NickelHook.mk 2 | 3 | override DBUS_IFACE_NAME := com.github.shermp.nickeldbus 4 | override DBUS_IFACE_XML := src/interface/$(DBUS_IFACE_NAME).xml 5 | override DBUS_IFACE_CFG := $(subst .,-,$(DBUS_IFACE_NAME)).conf 6 | override IFACE_DIR := src/interface 7 | 8 | override LIBRARY := libndb.so 9 | # NDB sources 10 | override SOURCES += src/ndb/nickeldbus.cc src/ndb/NDBDbus.cc src/ndb/NDBCfmDlg.cc src/ndb/NDBWidgets.cc src/ndb/util.cc $(IFACE_DIR)/ndb_adapter.cpp 11 | # NM sources 12 | override SOURCES += NickelMenu/src/util.c NickelMenu/src/action.c NickelMenu/src/action_c.c NickelMenu/src/action_cc.cc NickelMenu/src/kfmon.c 13 | override CFLAGS += -Wall -Wextra -Werror 14 | override CXXFLAGS += -Wall -Wextra -Werror -Wno-missing-field-initializers 15 | 16 | override CFLAGS += -DNDB_DBUS_IFACE_NAME='"$(DBUS_IFACE_NAME)"' 17 | override CXXFLAGS += -DNDB_DBUS_IFACE_NAME='"$(DBUS_IFACE_NAME)"' 18 | 19 | override PKGCONF += Qt5DBus Qt5Widgets 20 | 21 | override MOCS += src/ndb/NDBDbus.h src/ndb/NDBCfmDlg.h src/ndb/NDBWidgets.h $(IFACE_DIR)/ndb_adapter.h 22 | 23 | override ADAPTER := $(IFACE_DIR)/ndb_adapter.h 24 | override PROXY := $(IFACE_DIR)/ndb_proxy.h 25 | 26 | override KOBOROOT += res/$(DBUS_IFACE_CFG):/etc/dbus-1/system.d/$(DBUS_IFACE_CFG) 27 | override KOBOROOT += src/cli/qndb:/usr/bin/qndb 28 | override KOBOROOT += $(UNINSTALL_FILE):/mnt/onboard/.adds/nickeldbus 29 | 30 | override UNINSTALL_FILE := res/ndb_version 31 | 32 | override GENERATED += $(UNINSTALL_FILE) 33 | 34 | override GITIGNORE += $(PROXY:h=moc) $(PROXY:h=o) $(PROXY:h=moc.o) qdoc/html/ 35 | 36 | .PHONY: debug cli clean-cli gitignore-cli doc internal-doc dbuscfg interface uninstall-file 37 | 38 | interface: $(ADAPTER) $(PROXY) 39 | 40 | dbuscfg: 41 | script/make-dbus-conf.sh res/$(DBUS_IFACE_CFG) $(DBUS_IFACE_NAME) 42 | 43 | cli: interface 44 | cd src/cli && $(MAKE) 45 | 46 | clean-cli: 47 | cd src/cli && $(MAKE) clean 48 | 49 | gitignore-cli: 50 | cd src/cli && $(MAKE) gitignore 51 | 52 | clean: clean-cli 53 | 54 | gitignore: gitignore-cli 55 | 56 | internal-doc: 57 | cd qdoc/config && qdoc NickelDBus.qdocconf 58 | sed -i 's/This function was introduced in Qt/This function was introduced in NickelDBus/g' qdoc/html/ndb-ndbdbus.html 59 | doc: internal-doc 60 | cd qdoc/html && \ 61 | rm ndb.html && \ 62 | rm ndb-ndbcfmdlg* && \ 63 | rm ndb-ndbprogressbar* 64 | 65 | uninstall-file: 66 | echo "$(VERSION)" > $(UNINSTALL_FILE) 67 | 68 | all: uninstall-file 69 | 70 | debug: CFLAGS += -DDEBUG 71 | debug: CXXFLAGS += -DDEBUG 72 | debug: all 73 | 74 | $(SOURCES): $(ADAPTER) 75 | 76 | $(DBUS_IFACE_XML): src/ndb/NDBDbus.h | $(IFACE_DIR) 77 | qdbuscpp2xml -S -M -o $@ $< 78 | 79 | $(ADAPTER) : $(DBUS_IFACE_XML) 80 | cd $(IFACE_DIR) && qdbusxml2cpp -c NDBAdapter -a ndb_adapter $( 0 { 111 | go d.waitForSignal(sigNames, sigTimeout, serr) 112 | } 113 | call := obj.Call(fmt.Sprintf("%s.%s", d.dbusIface, methodName), 0, convArgs...) 114 | if call.Err != nil { 115 | return fmt.Errorf("error calling %s : %w", methodName, call.Err) 116 | } 117 | if len(call.Body) > 0 { 118 | for _, r := range call.Body { 119 | fmt.Printf("%v", r) 120 | } 121 | fmt.Printf("\n") 122 | } 123 | if len(sigNames) > 0 { 124 | if err := <-serr; err != nil { 125 | return fmt.Errorf("error waiting for signal after method call: %w", err) 126 | } 127 | } 128 | return nil 129 | } 130 | func (d *dbusCLI) waitForSignal(sigNames signals, sigTimeout int, err chan<- error) { 131 | var serr error 132 | sigFound := 0 133 | for _, s := range d.node.Interfaces[d.ifaceIndex].Signals { 134 | if sigNames.Exists(s.Name) { 135 | sigFound++ 136 | } 137 | } 138 | if sigFound != len(sigNames) { 139 | err <- fmt.Errorf("one or more signals not found") 140 | return 141 | } 142 | if serr = d.conn.AddMatchSignal( 143 | dbus.WithMatchObjectPath(d.dbusPath), 144 | dbus.WithMatchInterface(d.dbusIface), 145 | ); serr != nil { 146 | err <- fmt.Errorf("error adding match signal: %w", serr) 147 | return 148 | } 149 | c := make(chan *dbus.Signal) 150 | d.conn.Signal(c) 151 | timeout := time.Duration(sigTimeout) * time.Second 152 | if timeout == 0 { 153 | timeout = time.Duration(math.MaxInt64) 154 | } 155 | for { 156 | select { 157 | case v := <-c: 158 | name := v.Name[strings.LastIndex(v.Name, ".")+1:] 159 | if sigNames.Exists(name) { 160 | printSignal(v.Body, name) 161 | err <- nil 162 | return 163 | } 164 | case <-time.After(timeout): 165 | err <- fmt.Errorf("timeout after %ds", sigTimeout) 166 | return 167 | } 168 | } 169 | } 170 | 171 | func printSignal(val []interface{}, name string) { 172 | fmt.Printf("%s ", name) 173 | for _, s := range val { 174 | fmt.Printf("%v ", s) 175 | } 176 | fmt.Printf("\n") 177 | } 178 | 179 | func strToDBusType(typ string, val string) (interface{}, error) { 180 | var err error 181 | var b bool 182 | var i int64 183 | var ui uint64 184 | var f float64 185 | switch typ { 186 | case "y": 187 | if ui, err = strconv.ParseUint(val, 10, 8); err == nil { 188 | return byte(ui), nil 189 | } 190 | case "b": 191 | if b, err = strconv.ParseBool(val); err == nil { 192 | return b, nil 193 | } 194 | case "n": 195 | if i, err = strconv.ParseInt(val, 10, 16); err == nil { 196 | return int16(i), nil 197 | } 198 | case "q": 199 | if ui, err = strconv.ParseUint(val, 10, 16); err == nil { 200 | return uint16(ui), nil 201 | } 202 | case "i": 203 | if i, err = strconv.ParseInt(val, 10, 32); err == nil { 204 | return int32(i), nil 205 | } 206 | case "u": 207 | if ui, err = strconv.ParseUint(val, 10, 32); err == nil { 208 | return uint32(ui), nil 209 | } 210 | case "x": 211 | if i, err = strconv.ParseInt(val, 10, 64); err == nil { 212 | return int64(i), nil 213 | } 214 | case "t": 215 | if ui, err = strconv.ParseUint(val, 10, 64); err == nil { 216 | return uint64(ui), nil 217 | } 218 | case "h": 219 | if f, err = strconv.ParseFloat(val, 64); err == nil { 220 | return f, nil 221 | } 222 | case "s": 223 | return val, nil 224 | default: 225 | return nil, fmt.Errorf("unsupported dbus type '%s'", typ) 226 | } 227 | return nil, err 228 | } 229 | 230 | func main() { 231 | var err error 232 | d := dbusCLI{} 233 | d.dbusPath = dbus.ObjectPath("/nickeldbus") 234 | d.dbusIface = "com.github.shermp.nickeldbus" 235 | 236 | methodFlags := flag.NewFlagSet("method", flag.ExitOnError) 237 | // methodWaitForSig := d.methodFlags.String("wait-for-signal", "", "Wait for named signal after calling method.") 238 | // methodSigTimeout := d.methodFlags.Int("signal-timeout", 0, "When used with '--wait-for-signal', sets the time to wait for signal before timing out. 0 (default) disables timeout.") 239 | signalFlags := flag.NewFlagSet("signal", flag.ExitOnError) 240 | 241 | if len(os.Args) < 2 { 242 | fmt.Printf("Expected 'method' or 'signal' subcommands\n") 243 | os.Exit(1) 244 | } 245 | if err = d.initDBus(); err != nil { 246 | fmt.Printf("Error initializing dbus connection: %s\n", err.Error()) 247 | os.Exit(1) 248 | } 249 | defer d.conn.Close() 250 | switch os.Args[1] { 251 | case "method": 252 | sigNames := make(signals) 253 | methodFlags.Var(&sigNames, "signal", "Wait for named signal after calling method.") 254 | sigTimeout := methodFlags.Int("signal-timeout", 0, "When used with '--signal', sets the time to wait for signal before timing out. 0 (default) disables timeout.") 255 | methodFlags.Parse(os.Args[2:]) 256 | if methodFlags.NArg() < 1 { 257 | fmt.Printf("Expected method name\n") 258 | os.Exit(1) 259 | } 260 | methodName := methodFlags.Arg(0) 261 | methodArgs := methodFlags.Args()[1:] 262 | if err = d.callMethod(methodName, methodArgs, sigNames, *sigTimeout); err != nil { 263 | fmt.Printf("Error calling method: %s\n", err.Error()) 264 | os.Exit(1) 265 | } 266 | case "signal": 267 | sigTimeout := signalFlags.Int("timeout", 0, "Sets the time to wait for signal before timing out. 0 (default) disables timeout.") 268 | signalFlags.Parse(os.Args[2:]) 269 | if signalFlags.NArg() < 1 { 270 | fmt.Printf("Expected signal name\n") 271 | } 272 | sigNames := make(signals) 273 | for i := 0; i < signalFlags.NArg(); i++ { 274 | sigNames[signalFlags.Arg(i)] = struct{}{} 275 | } 276 | serr := make(chan error) 277 | go d.waitForSignal(sigNames, *sigTimeout, serr) 278 | if err = <-serr; err != nil { 279 | fmt.Printf("Error waiting for signal: %s\n", err.Error()) 280 | os.Exit(1) 281 | } 282 | default: 283 | fmt.Printf("Unknown command '%s'!\n", os.Args[1]) 284 | os.Exit(1) 285 | } 286 | os.Exit(0) 287 | } 288 | -------------------------------------------------------------------------------- /qdoc/config/NickelDBus.qdocconf: -------------------------------------------------------------------------------- 1 | # QDoc is a tool that constantly evolves to suit our needs, 2 | # and there are some compatibility issues between old and new 3 | # practices. For that reason, any QDoc configuration file needs to 4 | # include compat.qdocconf. 5 | 6 | project = NickelDBus 7 | description = Monitor and control aspects of Kobo's Nickel application 8 | 9 | include(compat.qdocconf) 10 | 11 | HTML.stylesheets = template/style/online.css 12 | HTML.extraimages += template/images/ico_out.png \ 13 | template/images/ico_note.png \ 14 | template/images/ico_note_attention.png \ 15 | template/images/btn_prev.png \ 16 | template/images/btn_next.png \ 17 | template/images/bullet_dn.png \ 18 | template/images/bullet_sq.png \ 19 | template/images/bgrContent.png 20 | 21 | include(ndb-html-header-online.qdocconf) 22 | 23 | # You can also specify file extensions manually. 24 | headers.fileextensions = "*.h *.hpp" 25 | sources.fileextensions = "*.cpp *.cc *.qml *.qdoc" 26 | 27 | # The outputdir variable specifies the directory 28 | # where QDoc will put the generated documentation. 29 | outputdir = ../html 30 | 31 | # The headerdirs variable specifies the directories 32 | # containing the header files associated 33 | # with the .cpp source files used in the documentation. 34 | headerdirs = .. ../../src/ndb/ 35 | 36 | # The sourcedirs variable specifies the 37 | # directories containing the .cpp or .qdoc 38 | # files used in the documentation. 39 | sourcedirs = .. ../../src/ndb 40 | 41 | # The exampledirs variable specifies the directories containing 42 | # the source code of the example files. 43 | exampledirs = . 44 | 45 | # The imagedirs variable specifies the 46 | # directories containing the images used in the documentation. 47 | imagedirs = ./images -------------------------------------------------------------------------------- /qdoc/config/compat.qdocconf: -------------------------------------------------------------------------------- 1 | macro.0 = "\\\\0" 2 | macro.n = "\\\\n" 3 | macro.r = "\\\\r" 4 | macro.img = "\\image" 5 | macro.endquote = "\\endquotation" 6 | macro.relatesto = "\\relates" 7 | 8 | spurious = "Missing comma in .*" \ 9 | "Missing pattern .*" 10 | -------------------------------------------------------------------------------- /qdoc/config/ndb-html-header-online.qdocconf: -------------------------------------------------------------------------------- 1 | #HTML Header for NickelDBus based on "HTML Header with Qt Project branding and online links" 2 | 3 | HTML.stylesheets = template/style/online.css 4 | 5 | #for including files into the qch file. Relative to the outputdir of a QDoc build. 6 | # $QT_INSTALL_DOCS/qtquick/style/online.css for example 7 | qhp.extraFiles += style/online.css 8 | 9 | HTML.headerstyles = \ 10 | " \n" 11 | 12 | HTML.endheader = \ 13 | "\n" 14 | 15 | HTML.postheader = \ 16 | "\n" \ 17 | "
\n" \ 18 | "
\n" \ 19 | "
\n" \ 20 | "
\n" \ 21 | "
    \n" \ 22 | 23 | HTML.postpostheader = \ 24 | "
\n" \ 25 | "
\n" \ 26 | "
\n" \ 27 | "
\n" \ 28 | "
\n" \ 29 | -------------------------------------------------------------------------------- /qdoc/config/template/images/arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shermp/NickelDBus/ab7ac0c7fee308b776a1359bb90898a21edfb54d/qdoc/config/template/images/arrow.png -------------------------------------------------------------------------------- /qdoc/config/template/images/arrow_bc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shermp/NickelDBus/ab7ac0c7fee308b776a1359bb90898a21edfb54d/qdoc/config/template/images/arrow_bc.png -------------------------------------------------------------------------------- /qdoc/config/template/images/arrow_down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shermp/NickelDBus/ab7ac0c7fee308b776a1359bb90898a21edfb54d/qdoc/config/template/images/arrow_down.png -------------------------------------------------------------------------------- /qdoc/config/template/images/bg_l.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shermp/NickelDBus/ab7ac0c7fee308b776a1359bb90898a21edfb54d/qdoc/config/template/images/bg_l.png -------------------------------------------------------------------------------- /qdoc/config/template/images/bg_l_blank.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shermp/NickelDBus/ab7ac0c7fee308b776a1359bb90898a21edfb54d/qdoc/config/template/images/bg_l_blank.png -------------------------------------------------------------------------------- /qdoc/config/template/images/bg_ll_blank.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shermp/NickelDBus/ab7ac0c7fee308b776a1359bb90898a21edfb54d/qdoc/config/template/images/bg_ll_blank.png -------------------------------------------------------------------------------- /qdoc/config/template/images/bg_r.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shermp/NickelDBus/ab7ac0c7fee308b776a1359bb90898a21edfb54d/qdoc/config/template/images/bg_r.png -------------------------------------------------------------------------------- /qdoc/config/template/images/bg_ul_blank.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shermp/NickelDBus/ab7ac0c7fee308b776a1359bb90898a21edfb54d/qdoc/config/template/images/bg_ul_blank.png -------------------------------------------------------------------------------- /qdoc/config/template/images/bgrContent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shermp/NickelDBus/ab7ac0c7fee308b776a1359bb90898a21edfb54d/qdoc/config/template/images/bgrContent.png -------------------------------------------------------------------------------- /qdoc/config/template/images/blu_dot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shermp/NickelDBus/ab7ac0c7fee308b776a1359bb90898a21edfb54d/qdoc/config/template/images/blu_dot.png -------------------------------------------------------------------------------- /qdoc/config/template/images/box_bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shermp/NickelDBus/ab7ac0c7fee308b776a1359bb90898a21edfb54d/qdoc/config/template/images/box_bg.png -------------------------------------------------------------------------------- /qdoc/config/template/images/breadcrumb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shermp/NickelDBus/ab7ac0c7fee308b776a1359bb90898a21edfb54d/qdoc/config/template/images/breadcrumb.png -------------------------------------------------------------------------------- /qdoc/config/template/images/btn_next.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shermp/NickelDBus/ab7ac0c7fee308b776a1359bb90898a21edfb54d/qdoc/config/template/images/btn_next.png -------------------------------------------------------------------------------- /qdoc/config/template/images/btn_prev.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shermp/NickelDBus/ab7ac0c7fee308b776a1359bb90898a21edfb54d/qdoc/config/template/images/btn_prev.png -------------------------------------------------------------------------------- /qdoc/config/template/images/bullet_dn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shermp/NickelDBus/ab7ac0c7fee308b776a1359bb90898a21edfb54d/qdoc/config/template/images/bullet_dn.png -------------------------------------------------------------------------------- /qdoc/config/template/images/bullet_gt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shermp/NickelDBus/ab7ac0c7fee308b776a1359bb90898a21edfb54d/qdoc/config/template/images/bullet_gt.png -------------------------------------------------------------------------------- /qdoc/config/template/images/bullet_sq.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shermp/NickelDBus/ab7ac0c7fee308b776a1359bb90898a21edfb54d/qdoc/config/template/images/bullet_sq.png -------------------------------------------------------------------------------- /qdoc/config/template/images/bullet_up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shermp/NickelDBus/ab7ac0c7fee308b776a1359bb90898a21edfb54d/qdoc/config/template/images/bullet_up.png -------------------------------------------------------------------------------- /qdoc/config/template/images/feedbackground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shermp/NickelDBus/ab7ac0c7fee308b776a1359bb90898a21edfb54d/qdoc/config/template/images/feedbackground.png -------------------------------------------------------------------------------- /qdoc/config/template/images/header_bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shermp/NickelDBus/ab7ac0c7fee308b776a1359bb90898a21edfb54d/qdoc/config/template/images/header_bg.png -------------------------------------------------------------------------------- /qdoc/config/template/images/home.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shermp/NickelDBus/ab7ac0c7fee308b776a1359bb90898a21edfb54d/qdoc/config/template/images/home.png -------------------------------------------------------------------------------- /qdoc/config/template/images/horBar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shermp/NickelDBus/ab7ac0c7fee308b776a1359bb90898a21edfb54d/qdoc/config/template/images/horBar.png -------------------------------------------------------------------------------- /qdoc/config/template/images/ico_note.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shermp/NickelDBus/ab7ac0c7fee308b776a1359bb90898a21edfb54d/qdoc/config/template/images/ico_note.png -------------------------------------------------------------------------------- /qdoc/config/template/images/ico_note_attention.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shermp/NickelDBus/ab7ac0c7fee308b776a1359bb90898a21edfb54d/qdoc/config/template/images/ico_note_attention.png -------------------------------------------------------------------------------- /qdoc/config/template/images/ico_out.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shermp/NickelDBus/ab7ac0c7fee308b776a1359bb90898a21edfb54d/qdoc/config/template/images/ico_out.png -------------------------------------------------------------------------------- /qdoc/config/template/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shermp/NickelDBus/ab7ac0c7fee308b776a1359bb90898a21edfb54d/qdoc/config/template/images/logo.png -------------------------------------------------------------------------------- /qdoc/config/template/images/page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shermp/NickelDBus/ab7ac0c7fee308b776a1359bb90898a21edfb54d/qdoc/config/template/images/page.png -------------------------------------------------------------------------------- /qdoc/config/template/images/page_bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shermp/NickelDBus/ab7ac0c7fee308b776a1359bb90898a21edfb54d/qdoc/config/template/images/page_bg.png -------------------------------------------------------------------------------- /qdoc/config/template/images/spinner.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shermp/NickelDBus/ab7ac0c7fee308b776a1359bb90898a21edfb54d/qdoc/config/template/images/spinner.gif -------------------------------------------------------------------------------- /qdoc/config/template/style/online.css: -------------------------------------------------------------------------------- 1 | img { 2 | -moz-box-shadow: 3px 3px 3px #ccc; 3 | -webkit-box-shadow: 3px 3px 3px #ccc; 4 | box-shadow: 3px 3px 3px #ccc; 5 | border: #8E8D8D 2px solid; 6 | margin-left: 0px; 7 | max-width: 800px; 8 | height: auto; 9 | } 10 | 11 | .content { 12 | margin: 15px 13 | } 14 | 15 | .content .indexboxcont li { 16 | font: normal bold 13px/1 Verdana 17 | } 18 | 19 | .content .normallist li { 20 | font: normal 13px/1 Verdana 21 | } 22 | 23 | .descr { 24 | margin-top: 35px; 25 | /*max-width: 75%;*/ 26 | margin-left: 5px; 27 | text-align: left; 28 | vertical-align: top; 29 | } 30 | 31 | .name { 32 | max-width: 75%; 33 | font-weight: 100; 34 | } 35 | 36 | tt { 37 | text-align: left 38 | } 39 | 40 | /* 41 | ----------- 42 | links 43 | ----------- 44 | */ 45 | 46 | .flags { 47 | text-decoration: none; 48 | text-height: 24px; 49 | } 50 | 51 | /* 52 | ------------------------------- 53 | NOTE styles 54 | ------------------------------- 55 | */ 56 | 57 | .notetitle, .tiptitle, .fastpathtitle { 58 | font-weight: bold 59 | } 60 | 61 | .attentiontitle, .cautiontitle, .dangertitle, .importanttitle, .remembertitle, .restrictiontitle { 62 | font-weight: bold 63 | } 64 | 65 | .note, .tip, .fastpath { 66 | background: #F2F2F2 url('../images/ico_note.png'); 67 | background-repeat: no-repeat; 68 | background-position: top left; 69 | padding: 5px; 70 | padding-left: 40px; 71 | padding-bottom: 10px; 72 | border: #999 1px dotted; 73 | color: #666666; 74 | margin: 5px; 75 | } 76 | 77 | .attention, .caution, .danger, .important, .remember, .restriction { 78 | background: #F2F2F2 url('../images/ico_note_attention.png'); 79 | background-repeat: no-repeat; 80 | background-position: top left; 81 | padding: 5px; 82 | padding-left: 40px; 83 | padding-bottom: 10px; 84 | border: #999 1px dotted; 85 | color: #666666; 86 | margin: 5px; 87 | } 88 | 89 | .qtref { 90 | display: block; 91 | top: -76px; 92 | z-index: 1; 93 | font-size: 11px; 94 | padding-right: 10px; 95 | float: right; 96 | } 97 | 98 | .naviNextPrevious { 99 | display: block; 100 | text-align: right; 101 | float: right; 102 | z-index: 1; 103 | padding-right: 10px; 104 | padding-top: 4px; 105 | } 106 | 107 | .naviNextPrevious > a.nextPage { 108 | background-image: url('../images/btn_next.png'); 109 | background-repeat: no-repeat; 110 | background-position: right; 111 | padding-right: 20px; 112 | height: 20px; 113 | margin-left: 30px; 114 | } 115 | 116 | .naviNextPrevious > a.prevPage { 117 | background-image: url('../images/btn_prev.png'); 118 | background-repeat: no-repeat; 119 | background-position: left; 120 | padding-left: 20px; 121 | height: 20px; 122 | padding-left: 20px; 123 | } 124 | 125 | .navigationbar { 126 | background-repeat: no-repeat; 127 | height: 33px; 128 | margin: 0px !important; 129 | padding: 0px !important; 130 | border-bottom: 1px solid rgb(209, 209, 209); 131 | background-image: -moz-linear-gradient(center top , rgb(246, 245, 245), rgb(239, 239, 239)); 132 | background-image: -webkit-gradient( linear, left bottom, left top, color-stop(0.0, #efefef), color-stop(0.5, #f6f5f5) ); 133 | border-radius: 10px 10px 0px 0px; 134 | } 135 | 136 | .navigationbar ul { 137 | margin: 0px; 138 | padding: 8px 0px 15px 15px; 139 | height: 20px; 140 | } 141 | 142 | .navigationbar li { 143 | list-style-type: none; 144 | float: left; 145 | font-size: 15px; 146 | } 147 | 148 | .navigationbar li a { 149 | display: block; 150 | text-decoration: none; 151 | background: url('../images/arrow_bc.png'); 152 | background-repeat: no-repeat; 153 | background-position: right; 154 | padding-right: 25px; 155 | font-size: inherit; 156 | } 157 | 158 | #buildversion { 159 | font-style: italic; 160 | font-size: small; 161 | float: right; 162 | margin-right: 5px; 163 | } 164 | 165 | /* 166 | ----------- 167 | headers 168 | ----------- 169 | */ 170 | 171 | @media screen { 172 | .title { 173 | color: #313131; 174 | font-size: 18px; 175 | font-weight: normal; 176 | left: 0; 177 | padding-bottom: 20px; 178 | padding-left: 10px; 179 | padding-top: 20px; 180 | border-bottom: 1px #CCC solid; 181 | font-weight: bold; 182 | margin-left: 0px; 183 | margin-right: 0px; 184 | } 185 | } 186 | 187 | h1 { 188 | margin: 0 189 | } 190 | 191 | h2, p.h2 { 192 | font: 500 16px/1.2 Arial; 193 | font-weight: 100; 194 | background-color: #F2F3F4; 195 | padding: 4px; 196 | padding-left: 14px; 197 | margin-bottom: 30px; 198 | margin-top: 30px; 199 | margin-left: -10px; 200 | margin-right: -5px; 201 | border-top: #E0E0DE 1px solid; 202 | border-bottom: #E0E0DE 1px solid; 203 | max-width: 99%; 204 | overflow: hidden; 205 | } 206 | 207 | /* h3 { 208 | font: 500 14px/1.2 Arial; 209 | font-weight: 100; 210 | text-decoration: underline; 211 | margin-bottom: 30px; 212 | margin-top: 30px; 213 | } */ 214 | 215 | h3.fn, span.fn { 216 | border-width: 1px; 217 | border-style: solid; 218 | border-color: #E6E6E6; 219 | -moz-border-radius: 7px 7px 7px 7px; 220 | -webkit-border-radius: 7px 7px 7px 7px; 221 | border-radius: 7px 7px 7px 7px; 222 | background-color: #F6F6F6; 223 | word-spacing: 3px; 224 | padding: 5px 5px; 225 | text-decoration: none; 226 | font-weight: bold; 227 | max-width: 75%; 228 | font-size: 14px; 229 | margin: 0px; 230 | margin-top: 45px; 231 | } 232 | 233 | .name { 234 | color: #1A1A1A 235 | } 236 | 237 | .type { 238 | color: #808080 239 | } 240 | 241 | @media print { 242 | .title { 243 | color: #0066CB; 244 | font-size: 32px; 245 | font-weight: normal; 246 | left: 0; 247 | position: absolute; 248 | right: 0; 249 | top: 0; 250 | } 251 | } 252 | 253 | /* 254 | ----------------- 255 | table styles 256 | ----------------- 257 | */ 258 | 259 | .table img { 260 | border: none; 261 | margin-left: 0px; 262 | -moz-box-shadow: 0px 0px 0px #fff; 263 | -webkit-box-shadow: 0px 0px 0px #fff; 264 | box-shadow: 0px 0px 0px #fff; 265 | } 266 | 267 | /* table with border alternative colours*/ 268 | 269 | table, pre { 270 | -moz-border-radius: 7px 7px 7px 7px; 271 | -webkit-border-radius: 7px 7px 7px 7px; 272 | border-radius: 7px 7px 7px 7px; 273 | background-color: #F6F6F6; 274 | border: 1px solid #E6E6E6; 275 | border-collapse: separate; 276 | font-size: 12px; 277 | line-height: 1.2; 278 | margin-bottom: 25px; 279 | margin-left: 15px; 280 | font-size: 12px; 281 | line-height: 1.2; 282 | margin-bottom: 25px; 283 | margin-left: 15px; 284 | } 285 | 286 | table tr.even { 287 | background-color: white; 288 | color: #66666E; 289 | } 290 | 291 | table tr.odd { 292 | background-color: #F6F6F6; 293 | color: #66666E; 294 | } 295 | 296 | table thead { 297 | text-align: left; 298 | padding-left: 20px; 299 | background-color: #e1e0e0; 300 | border-left: none; 301 | border-right: none; 302 | } 303 | 304 | table thead th { 305 | padding-top: 5px; 306 | padding-left: 10px; 307 | padding-bottom: 5px; 308 | border-bottom: 2px solid #D1D1D1; 309 | padding-right: 10px; 310 | } 311 | 312 | table td { 313 | padding: 3px 15px 3px 20px; 314 | border-bottom: #CCC dotted 1px; 315 | } 316 | 317 | table th { 318 | text-align: left; 319 | padding-left: 20px; 320 | } 321 | 322 | table p { 323 | margin: 0px 324 | } 325 | 326 | /* table bodless & white*/ 327 | 328 | .borderless { 329 | border-radius: 0px 0px 0px 0px; 330 | background-color: #fff; 331 | border: 1px solid #fff; 332 | } 333 | 334 | .borderless td { 335 | border: none; 336 | border-bottom: #fff dotted 1px; 337 | } 338 | 339 | .borderless tr { 340 | background-color: #FFF; 341 | color: #66666E; 342 | } 343 | 344 | /* 345 | ----------- 346 | List 347 | ----------- 348 | */ 349 | 350 | ul { 351 | padding-bottom: 2px 352 | } 353 | 354 | li { 355 | margin-bottom: 10px; 356 | padding-left: 8px; 357 | list-style: outside; 358 | list-style-type: square; 359 | text-align: left; 360 | } 361 | 362 | ol { 363 | margin: 10px; 364 | padding: 0; 365 | } 366 | 367 | ol > li { 368 | margin-left: 30px; 369 | padding-left: 8px; 370 | list-style: decimal; 371 | } 372 | 373 | .centerAlign { 374 | text-align: left 375 | } 376 | 377 | .cpp { 378 | display: block; 379 | margin: 10px; 380 | overflow: auto; 381 | padding: 20px 20px 20px 20px; 382 | } 383 | 384 | .js { 385 | display: block; 386 | margin: 10px; 387 | overflow: auto; 388 | padding: 20px 20px 20px 20px; 389 | } 390 | 391 | .footerNavi { 392 | width: auto; 393 | text-align: right; 394 | margin-top: 50px; 395 | z-index: 1; 396 | } 397 | 398 | .memItemLeft { 399 | padding-right: 3px 400 | } 401 | 402 | .memItemRight { 403 | padding: 3px 15px 3px 0 404 | } 405 | 406 | .qml { 407 | display: block; 408 | margin: 10px; 409 | overflow: auto; 410 | padding: 20px 20px 20px 20px; 411 | } 412 | 413 | .qmldefault { 414 | padding-left: 5px; 415 | float: right; 416 | color: red; 417 | } 418 | 419 | .qmlreadonly { 420 | padding-left: 5px; 421 | float: right; 422 | color: #254117; 423 | } 424 | 425 | .rightAlign { 426 | padding: 3px 5px 3px 10px; 427 | text-align: right; 428 | } 429 | 430 | .qmldoc { 431 | margin-left: 15px 432 | } 433 | 434 | /* 435 | ----------- 436 | Content table 437 | ----------- 438 | */ 439 | 440 | @media print { 441 | .toc { 442 | float: right; 443 | clear: right; 444 | padding-bottom: 10px; 445 | padding-top: 50px; 446 | width: 100%; 447 | background-image: url('../images/bgrContent.png'); 448 | background-position: top; 449 | background-repeat: no-repeat; 450 | } 451 | } 452 | 453 | @media screen { 454 | .toc { 455 | vertical-align: top; 456 | -moz-border-radius: 7px 7px 7px 7px; 457 | -webkit-border-radius: 7px 7px 7px 7px; 458 | border-radius: 7px 7px 7px 7px; 459 | background: #FFF url('../images/bgrContent.png'); 460 | background-position: top; 461 | background-repeat: repeat-x; 462 | border: 1px solid #E6E6E6; 463 | padding-left: 5px; 464 | padding-bottom: 10px; 465 | height: auto; 466 | width: 200px; 467 | text-align: left; 468 | /* margin-left: 20px; */ 469 | } 470 | } 471 | 472 | .toc h3 { 473 | text-decoration: none 474 | } 475 | 476 | .toc h3 { 477 | font: 500 14px/1.2 Arial; 478 | font-weight: 100; 479 | padding: 0px; 480 | margin: 0px; 481 | padding-top: 5px; 482 | padding-left: 5px; 483 | } 484 | 485 | .toc ul { 486 | padding-left: 10px; 487 | padding-right: 5px; 488 | padding-top: 10px; 489 | } 490 | 491 | .toc ul li { 492 | margin-left: 15px; 493 | list-style-image: url('../images/blu_dot.png'); 494 | list-style: outside; 495 | marker-offset: 0px; 496 | margin-bottom: 8px; 497 | padding-left: 0px; 498 | } 499 | 500 | .toc .level1 { 501 | border: none 502 | } 503 | 504 | .toc .level2 { 505 | border: none; 506 | margin-left: 25px; 507 | } 508 | 509 | .level3 { 510 | border: none; 511 | margin-left: 30px; 512 | } 513 | 514 | .clearfix { 515 | clear: both 516 | } 517 | 518 | /* start index box */ 519 | 520 | .indexbox { 521 | width: 100%; 522 | display: inline-block; 523 | } 524 | 525 | .indexbox .indexIcon { 526 | width: 11% 527 | } 528 | 529 | .indexbox .indexIcon span { 530 | display: block 531 | } 532 | 533 | .indexboxcont { 534 | display: block 535 | } 536 | 537 | .indexboxcont .sectionlist { 538 | display: inline-block; 539 | vertical-align: top; 540 | width: 32.5%; 541 | padding: 0; 542 | } 543 | 544 | .indexboxcont .sectionlist ul { 545 | margin-bottom: 20px 546 | } 547 | 548 | .indexboxcont .sectionlist ul li { 549 | line-height: 1.5 550 | } 551 | 552 | .indexboxcont .indexIcon { 553 | width: 11%; 554 | *width: 18%; 555 | _width: 18%; 556 | overflow: hidden; 557 | } 558 | 559 | .indexboxcont .section { 560 | float: left 561 | } 562 | 563 | .indexboxcont .section { 564 | display: inline-block; 565 | width: 49%; 566 | *width: 42%; 567 | _width: 42%; 568 | padding: 0 2% 0 1%; 569 | vertical-align: top; 570 | } 571 | 572 | .indexboxcont .section p { 573 | padding-top: 20px; 574 | padding-bottom: 20px; 575 | } 576 | 577 | .indexboxcont:after { 578 | content: "."; 579 | display: block; 580 | height: 0; 581 | clear: both; 582 | visibility: hidden; 583 | } 584 | 585 | /* 586 | ----------- 587 | Landing page 588 | ----------- 589 | */ 590 | 591 | .col-group { 592 | white-space: nowrap; 593 | vertical-align: top; 594 | } 595 | 596 | .col-1 { 597 | display: inline-block; 598 | white-space: normal; 599 | width: 70%; 600 | height: 100%; 601 | float: left; 602 | } 603 | 604 | .col-1 h1 { 605 | margin: 20px 0 0 0 606 | } 607 | 608 | .col-2 { 609 | display: inline-block; 610 | white-space: normal; 611 | width: 25%; 612 | margin: 0 0 0 50px; 613 | } 614 | 615 | .sectionlist { 616 | width: 100% !important 617 | } 618 | 619 | /* 620 | Additions from Qt Project 621 | */ 622 | 623 | body { 624 | background: #E8E8E8; 625 | margin: 0px; 626 | font-family: "Open Sans",sans-serif !important; 627 | } 628 | 629 | .qt13a-twoCol { 630 | width: 23.46939%; 631 | float: left; 632 | margin-right: 2.04082%; 633 | display: inline; 634 | } 635 | 636 | .qt13a-fourCol { 637 | width: 48.97959%; 638 | float: left; 639 | margin-right: 2.04082%; 640 | display: inline; 641 | } 642 | 643 | .qt13a-sixCol { 644 | width: 70.4898%; 645 | float: left; 646 | margin-right: 2.04082%; 647 | display: inline; 648 | } 649 | 650 | .qt13a-eightCol { 651 | width: 100%; 652 | float: left; 653 | margin-right: 2.04082%; 654 | display: inline; 655 | } 656 | 657 | .qt13a-fiveCol { 658 | width: 17.35537%; 659 | float: left; 660 | margin-right: 3.30579%; 661 | display: inline; 662 | } 663 | 664 | .qt13a-fiveCol:nth-child(2n) { 665 | float: left; 666 | margin-right: 3.30579%; 667 | } 668 | 669 | .qt13a-omega { 670 | float: right; 671 | margin-right: 0; 672 | *margin-left: -20px; 673 | display: inline; 674 | } 675 | 676 | .qt13a-last { 677 | float: right; 678 | margin-right: 0; 679 | *margin-left: -20px; 680 | display: inline; 681 | } 682 | 683 | .qt13a-container { 684 | *zoom: 1; 685 | padding-left: 20px; 686 | padding-right: 20px; 687 | margin-left: auto; 688 | margin-right: auto; 689 | max-width: 1045px; 690 | } 691 | 692 | .qt13a-container:after { 693 | content: ""; 694 | display: table; 695 | clear: both; 696 | } 697 | 698 | .qt13a-container.qt13a-dynamic { 699 | max-width: 1295px 700 | } 701 | 702 | .qt13a-no-bg-img { 703 | background-image: none !important 704 | } 705 | 706 | .qt13a-wrapper { 707 | overflow: hidden 708 | } 709 | 710 | .content-view { 711 | position: relative; 712 | overflow: hidden; 713 | } 714 | 715 | #qt13a-header { 716 | background: url('../images/Qt-header-bg.jpg') repeat; 717 | min-height: 126px; 718 | padding: 0; 719 | margin: 0; 720 | min-width: 1045px; 721 | margin-bottom: 18px; 722 | } 723 | 724 | #qt13a-header .qt13a-nav-divider-left { 725 | border-left: 1px solid #35322f; 726 | padding-left: 10px; 727 | margin-left: 5px; 728 | font-size: 13px; 729 | } 730 | 731 | #qt13a-header #qt13a-title_nav { 732 | padding-top: 34px; 733 | width: 87.37374%; 734 | float: left; 735 | margin-right: 1.0101%; 736 | display: inline; 737 | float: right; 738 | margin-right: 0; 739 | *margin-left: -20px; 740 | display: inline; 741 | } 742 | 743 | #qt13a-header .qt13a-gradient { 744 | background: url('../images/Qt-gradient.png') repeat-x; 745 | background-position: bottom; 746 | margin: 0; 747 | min-height: 126px; 748 | padding: 0; 749 | } 750 | 751 | #qt13a-header p.qt13a-title { 752 | font-size: 24px; 753 | margin: 0 0 0 0px; 754 | letter-spacing: -1px; 755 | color: #35322f; 756 | font-weight: 600; 757 | } 758 | 759 | #qt13a-header p.qt13a-title a { 760 | font-weight: 600; 761 | color: #35322f; 762 | } 763 | 764 | #qt13a-header p.qt13a-title a:hover { 765 | color: #35322f; 766 | text-decoration: none; 767 | } 768 | 769 | #qt13a-header #qt13a-title { 770 | padding: 0px 0 0 0px; 771 | padding-bottom: 0px; 772 | } 773 | 774 | #qt13a-header #qt13a-logo { 775 | float: left; 776 | width: 11.61616%; 777 | float: left; 778 | margin-right: 1.0101%; 779 | display: inline; 780 | margin: 20px 0px 10px 0; 781 | min-width: 50px; 782 | } 783 | 784 | #qt13a-header #qt13a-logo .qt13a-site-logo { 785 | background: url('../images/Qt-logo.png') no-repeat; 786 | text-indent: -100em; 787 | overflow: hidden; 788 | display: block; 789 | height: 90px; 790 | -moz-box-shadow: none; 791 | -webkit-box-shadow: none; 792 | box-shadow: none; 793 | } 794 | 795 | #qt13a-header #qt13a-logo img { 796 | float: left; 797 | border: 0; 798 | -moz-box-shadow: none; 799 | -webkit-box-shadow: none; 800 | box-shadow: none; 801 | } 802 | 803 | #qt13a-header .qt13a-nav { 804 | background: none 805 | } 806 | 807 | #qt13a-header .qt13a-nav .qt13a-nav-divider-left { 808 | border-left: 1px solid #35322f; 809 | padding-left: 20px; 810 | } 811 | 812 | #qt13a-header .qt13a-nav .qt13a-nav-small a { 813 | font-size: 13px 814 | } 815 | 816 | #qt13a-header .qt13a-nav ul { 817 | margin: 0 0 0 0px; 818 | padding: 11px 0 0; 819 | background: none; 820 | } 821 | 822 | #qt13a-header .qt13a-nav ul li.devnet-active a { 823 | color: #fff 824 | } 825 | 826 | #qt13a-header .qt13a-nav ul li { 827 | display: inline-block; 828 | width: auto; 829 | padding: 0 2.88% 0 0; 830 | margin: 0; 831 | border: 0; 832 | *display: inline; 833 | zoom: 1; 834 | } 835 | 836 | #qt13a-header .qt13a-nav ul li a { 837 | color: #35322f; 838 | margin: 0; 839 | padding: 0; 840 | line-height: 18px; 841 | font-size: 18px; 842 | } 843 | 844 | #qt13a-header .qt13a-nav ul li a:hover, #qt13a-header .qt13a-nav ul li a:active, #qt13a-header .qt13a-nav ul li a.active { 845 | color: #fff; 846 | text-decoration: none; 847 | } 848 | 849 | #qt13a-register_search { 850 | display: block; 851 | font-variant: 400; 852 | float: right; 853 | } 854 | 855 | #qt13a-register { 856 | padding: 34px 0px 0; 857 | float: right; 858 | text-align: right; 859 | color: #1e1b18; 860 | } 861 | 862 | #qt13a-register .qt13a-link-divider { 863 | padding: 0 5px 864 | } 865 | 866 | #qt13a-register a { 867 | color: #1e1b18; 868 | font-weight: 400; 869 | font-size: 13px; 870 | padding-left: 13px; 871 | } 872 | 873 | #qt13a-register a:visited { 874 | color: #1e1b18 875 | } 876 | 877 | #qt13a-register a:hover { 878 | color: #fff; 879 | text-decoration: none; 880 | } 881 | 882 | #search { 883 | margin-top: 23px 884 | } 885 | 886 | #qt13a-footer { 887 | background: url('../images/Qt-header-bg.jpg') repeat; 888 | margin: 0; 889 | } 890 | 891 | #qt13a-footer .qt13a-container { 892 | padding: 36px 0 893 | } 894 | 895 | #qt13a-footer .qt13a-gradient { 896 | background: url('../images/Qt-dark_gradient.png') repeat-x; 897 | background-position: bottom; 898 | margin: 0; 899 | min-height: 126px; 900 | padding: 0; 901 | } 902 | 903 | #qt13a-footer .qt13a-shadow { 904 | background: transparent url('../images/Qt-footer_shadow.png') repeat-x top center 905 | } 906 | 907 | #qt13a-footer .qt13a-last { 908 | float: right; 909 | margin-right: 0; 910 | *margin-left: -20px; 911 | display: inline; 912 | } 913 | 914 | #qt13a-footer ul { 915 | width: 17.35537%; 916 | float: left; 917 | margin-right: 3.30579%; 918 | display: inline; 919 | padding-left: 0; 920 | list-style-type: none; 921 | } 922 | 923 | #qt13a-footer ul li a.qt13a-some-icon { 924 | width: 32px; 925 | height: 32px; 926 | background-repeat: none; 927 | text-indent: -300em; 928 | overflow: hidden; 929 | display: -moz-inline-stack; 930 | display: inline-block; 931 | vertical-align: middle; 932 | *vertical-align: auto; 933 | zoom: 1; 934 | *display: inline; 935 | } 936 | 937 | #qt13a-footer ul li a { 938 | font-family: "Open Sans",sans-serif; 939 | font-size: 13px; 940 | color: #35322f; 941 | padding: 0; 942 | font-weight: 400; 943 | } 944 | 945 | #qt13a-footer ul li a:hover, #qt13a-footer ul li a:active { 946 | color: #35322f; 947 | text-decoration: underline; 948 | } 949 | 950 | #qt13a-footer .qt13a-title a, #qt13a-footer .qt13a-title { 951 | padding: 18px 0 18px; 952 | font-weight: 400; 953 | letter-spacing: -0.5pt; 954 | color: #35322f; 955 | font-size: 18px; 956 | margin: 0; 957 | } 958 | 959 | .qt13a-copyright { 960 | border-top: 1px solid #000; 961 | background: url('../images/Qt-footer-bg.jpg') repeat; 962 | margin: 0; 963 | padding: 36px 0; 964 | font-weight: 400; 965 | font-size: 0.84615em; 966 | line-height: 1.63636em; 967 | } 968 | 969 | .qt13a-copyright p { 970 | padding: 0; 971 | color: #aeadac; 972 | font-size: 11px; 973 | } 974 | 975 | .qt13a-copyright a { 976 | color: #328930 977 | } 978 | 979 | .qt13a-copyright a:visited { 980 | color: #328930 981 | } 982 | 983 | .searchbox { 984 | display: block; 985 | overflow: hidden; 986 | padding: 0px 35px 0 5px; 987 | } 988 | 989 | .content-view { 990 | position: relative; 991 | overflow: hidden; 992 | } 993 | 994 | p, li, p.forum-overview-title, p.forum-description, p.desc, p.forum-lastpost, div.navigationbars li, div.block-profile div { 995 | font-size: 13px 996 | } 997 | 998 | p.forum-description.desc { 999 | font-size: 13px !important 1000 | } 1001 | 1002 | .steps li { 1003 | font-size: 16px 1004 | } 1005 | 1006 | div.license p, div.notes p { 1007 | font-size: 12px !important 1008 | } 1009 | 1010 | a { 1011 | color: #44a51c; 1012 | text-decoration: none; 1013 | } 1014 | 1015 | .wrap { 1016 | padding-left: 30px 1017 | } 1018 | 1019 | a:visited { 1020 | color: #007330; 1021 | text-align: left; 1022 | } 1023 | 1024 | a:hover { 1025 | color: #44a51c; 1026 | text-align: left; 1027 | } 1028 | 1029 | a:visited:hover { 1030 | color: #44a51c; 1031 | text-align: left; 1032 | } 1033 | 1034 | a:link { 1035 | color: #007330; 1036 | text-decoration: none; 1037 | text-align: left; 1038 | } 1039 | 1040 | .main { 1041 | padding: 0px 30px 30px 30px 1042 | } 1043 | 1044 | .main-rounded { 1045 | display: inline-block; 1046 | background: none repeat scroll 0% 0% rgb(255,255,255); 1047 | width: 100%; 1048 | border: 1px solid #DADADA; 1049 | border-radius: 10px 10px 10px 10px; 1050 | box-shadow: 0 0 3px #C4C4C4; 1051 | padding-bottom: 30px; 1052 | } 1053 | -------------------------------------------------------------------------------- /qdoc/pages.qdoc: -------------------------------------------------------------------------------- 1 | /*! 2 | \page index.html 3 | 4 | \indexpage NickelDBus 5 | 6 | \startpage NickelDBus 7 | 8 | \nextpage {NDB::NDBDbus}{API Documentation} 9 | 10 | \title NickelDBus 11 | 12 | \section1 Introduction 13 | 14 | NickelDBus is a mod for Kobo e-readers. Heavily inspired by 15 | \l {https://github.com/pgaskin/NickelMenu}{NickelMenu}, it 16 | allows developers to perform many of the same actions as NickelMenu, but 17 | from scripts or programs, instead of from the UI. 18 | 19 | As well as the ability to trigger actions, NickelDBus also allows you to 20 | wait on a limited selection of signals. Such signals include knowing when 21 | the content import process has completed, or whether WiFi has connected, 22 | among others. 23 | 24 | This is all achieved through the magic of d-bus. NickelDBus registers itself 25 | on the \c system bus. 26 | 27 | You can follow the development of NickelDBus at the 28 | \l {https://github.com/shermp/NickelDBus}{GitHub repository}. 29 | 30 | \section1 Installation 31 | 32 | Installing NickelDBus is simple. Simply go to the 33 | \l {https://github.com/shermp/NickelDBus/releases/latest}{latest release} page and 34 | download the \c KoboRoot.tgz file. 35 | 36 | Copy the downloaded \c KoboRoot.tgz to the \c .kobo directory on the root 37 | of your kobo when plugged into USB. Eject/disconnect your Kobo, and it will 38 | automatically install itself. 39 | 40 | There is no need to configure anything after installation. 41 | 42 | \note NickelDBus should survive factory resets. 43 | 44 | \note to check what version of NickelDBus you have installed, open the file 45 | `.adds/nickeldbus` in a text editor. Applications should use the provided 46 | \c ndbVersion method to get the current NickelDBus version instead of 47 | parsing this file. 48 | 49 | \section1 Upgrading 50 | 51 | To upgrade NickelDBus, simply follow the same procedure as installing it. 52 | 53 | \section1 Uninstallation 54 | 55 | If you ever want to remove NickelDBus, simply connect your Kobo to your 56 | computer over USB and delete the file called \c nickeldbus in the \c .adds 57 | directory. 58 | 59 | Then disconnect your Kobo, and reboot. NickelDBus should now be removed. 60 | 61 | \section1 Developer Documentation 62 | 63 | \note Please do not directly install NickelDBus when installing your own 64 | application. If you wish to include NickelDBus as a convenience for 65 | your users, consider performing an install or upgrade (never downgrade) 66 | during your application start-up process. 67 | 68 | NickelDBus presents itself on the d-bus \c system bus. It has an interface 69 | of \c com.github.shermp.nickeldbus and a path of \c /nickeldbus. 70 | 71 | To interact with NickelDBus, you can use language bindings for your favourite 72 | programming language. Most if not all languages have bindings available. 73 | 74 | \section2 Usage 75 | 76 | \section3 CLI Tools 77 | 78 | Shell script users may use the standard \c dbus-send and \c dbus-monitor tools. 79 | Programs like qdbus and gdbus are also available. 80 | 81 | Alternatively, NickelDBus installs a small tool called \c qndb if you wish to 82 | use it. \c qndb allows you to call a method, or wait for a signal, or call 83 | a method then wait for a signal. 84 | 85 | \section4 qndb 86 | 87 | The \c qndb usage is as follows: 88 | 89 | \code 90 | Usage: qndb [options] [args...] 91 | Qt CLI for NickelDBus 92 | 93 | Options: 94 | -h, --help Displays this help. 95 | -v, --version Displays version information. 96 | -s, --signal Wait for signal, and prints its output, if any. 97 | -t, --timeout Signal timeout in milliseconds. 98 | -m, --method Method to invoke. 99 | -a, --api Print API usage 100 | 101 | Arguments: 102 | arguments Arguments to pass to method. Have no affect when 103 | a method is not set. 104 | \endcode 105 | 106 | And here are a few examples: 107 | 108 | Print the current NickelDBus version 109 | \code qndb -m ndbVersion \endcode 110 | 111 | Show a toast on-screen for 3 seconds, with message 'Hello World!': 112 | \code qndb -m mwcToast 3000 "Hello World" \endcode 113 | 114 | Trigger library rescan, and wait for content import to complete, with a 30 second timeout: 115 | \code qndb -t 30000 -s pfmDoneProcessing -m pfmRescanBooksFull \endcode 116 | 117 | \note Even though \c qndb may time out, the content import process will not be aborted. 118 | 119 | \section3 Language Bindings 120 | 121 | Most languages will have d-bus bindings available. NickelDBus and \c qndb were written 122 | in Qt using QtDBus. 123 | 124 | \section3 API Documentation 125 | 126 | The API is documented \l {NDB::NDBDbus}{here}. It is Qt based documentation, but it should 127 | be easy to determine what's needed for other languages or CLI tools. 128 | 129 | \section2 Compiling NickelDBus 130 | 131 | NickelDBus is a Qt and C++ based project. It was designed to be used with 132 | \l {https://github.com/pgaskin/NickelTC}{NickelTC}. As such, the Makefile expects that 133 | to be available. 134 | 135 | To build everything from scratch, run: 136 | \code make clean && make && make cli && make koboroot \endcode 137 | 138 | That will compile the library, \c qndb and package it up into a \c KoboRoot.tgz ready to 139 | be installed onto a Kobo. 140 | 141 | To make this documentation, run 142 | \code make doc \endcode 143 | 144 | If you are developing NickelDBus, you will probably want to run 145 | \code make interface \endcode 146 | 147 | if you haven't already run \c make so that you have the auto-generated adapter and proxy 148 | code and header files. 149 | 150 | */ 151 | -------------------------------------------------------------------------------- /res/com-github-shermp-nickeldbus.conf: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /script/make-dbus-conf.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | conf_file=$1 4 | iface_name=$2 5 | 6 | tee "$conf_file" < 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | EOF -------------------------------------------------------------------------------- /src/cli/.gitignore: -------------------------------------------------------------------------------- 1 | # make gitignore 2 | .kdev4/ 3 | *.kdev4 4 | .kateconfig 5 | .vscode/ 6 | .idea/ 7 | .clangd/ 8 | .cache/ 9 | compile_commands.json 10 | qndb 11 | qndb.o 12 | ndb_cli.o 13 | ndb_cli.moc 14 | ndb_cli.moc.o 15 | -------------------------------------------------------------------------------- /src/cli/Makefile: -------------------------------------------------------------------------------- 1 | CROSS_COMPILE = arm-nickel-linux-gnueabihf- 2 | MOC = moc 3 | CC = $(CROSS_COMPILE)gcc 4 | CXX = $(CROSS_COMPILE)g++ 5 | PKG_CONFIG = $(CROSS_COMPILE)pkg-config 6 | STRIP = $(CROSS_COMPILE)strip 7 | AS = $(CROSS_COMPILE)as 8 | # NOTE: Point to the GCC wrappers for sane LTO handling. 9 | # But don't use LTO, it's terrible on GCC 4.9 10 | AR = $(CROSS_COMPILE)gcc-ar 11 | RANLIB = $(CROSS_COMPILE)gcc-ranlib 12 | NM = $(CROSS_COMPILE)gcc-nm 13 | LD = $(CROSS_COMPILE)ld 14 | READELF = $(CROSS_COMPILE)readelf 15 | OBJCOPY = $(CROSS_COMPILE)objcopy 16 | OBJDUMP = $(CROSS_COMPILE)objdump 17 | STRINGS = $(CROSS_COMPILE)strings 18 | 19 | override nh_comma := , 20 | 21 | # pkgconf function 22 | override define pkgconf = 23 | $(if $(filter-out undefined,$(origin $(strip $(1))_CFLAGS) $(origin $(strip $(1))_LIBS)) \ 24 | ,$(info -- Using provided CFLAGS and LIBS for $(strip $(2))) \ 25 | ,$(if $(shell $(PKG_CONFIG) --exists $(strip $(2)) >/dev/null 2>/dev/null && echo y) \ 26 | ,$(info -- Found $(strip $(2)) ($(shell $(PKG_CONFIG) --modversion $(strip $(2)))) with pkg-config) \ 27 | $(eval $(strip $(1))_CFLAGS := $(shell $(PKG_CONFIG) --silence-errors --cflags $(strip $(2)))) \ 28 | $(eval $(strip $(1))_LIBS := $(shell $(PKG_CONFIG) --silence-errors --libs $(strip $(2)))) \ 29 | $(if $(strip $(3)) \ 30 | ,$(if $(shell $(PKG_CONFIG) $(strip $(3)) $(strip $(2)) >/dev/null 2>/dev/null && echo y) \ 31 | ,$(info .. Satisfies constraint $(strip $(3))) \ 32 | ,$(info .. Does not satisfy constraint $(strip $(3))) \ 33 | $(error Dependencies do not satisfy constraints)) \ 34 | ,) \ 35 | ,$(info -- Could not automatically detect $(strip $(2)) with pkg-config. Please specify $(strip $(1))_CFLAGS and/or $(strip $(1))_LIBS manually) \ 36 | $(error Missing dependencies))) 37 | endef 38 | 39 | CFLAGS ?= -O2 -march=armv7-a -mtune=cortex-a8 -mfpu=neon -mfloat-abi=hard -mthumb 40 | CXXFLAGS ?= -O2 -march=armv7-a -mtune=cortex-a8 -mfpu=neon -mfloat-abi=hard -mthumb 41 | LDFLAGS ?= -Wl,--as-needed 42 | 43 | override PKGCONF := Qt5Core Qt5DBus Qt5Widgets 44 | 45 | # transform `pkg` into `PKG,pkg` in `$(PKGCONF)` 46 | override PKGCONF := \ 47 | $(foreach dep,$(PKGCONF) \ 48 | ,$(strip $(if $(findstring $(nh_comma),$(dep)) \ 49 | ,$(dep) \ 50 | ,$(shell echo -n "$(dep)" | tr '[:lower:]' '[:upper:]')$(nh_comma)$(dep)))) 51 | 52 | # call pkgconf for each item in `$(PKGCONF)` 53 | $(foreach dep,$(PKGCONF) \ 54 | ,$(call pkgconf \ 55 | ,$(word 1,$(subst $(nh_comma), ,$(dep))) \ 56 | ,$(word 2,$(subst $(nh_comma), ,$(dep))) \ 57 | ,$(word 3,$(subst $(nh_comma), ,$(dep))))) 58 | 59 | # add flags 60 | override CFLAGS += $(foreach dep,$(PKGCONF),$($(word 1,$(subst $(nh_comma), ,$(dep)))_CFLAGS)) 61 | override CXXFLAGS += $(foreach dep,$(PKGCONF),$($(word 1,$(subst $(nh_comma), ,$(dep)))_CFLAGS)) 62 | override LDFLAGS += $(foreach dep,$(PKGCONF),$($(word 1,$(subst $(nh_comma), ,$(dep)))_LIBS)) 63 | 64 | override CFLAGS += -std=gnu11 -pthread 65 | override CXXFLAGS += -std=gnu++11 -pthread 66 | override LDFLAGS += -Wl,--no-undefined -Wl,-rpath,/usr/local/Kobo -Wl,-rpath,/usr/local/Qt-5.2.1-arm/lib -pthread -ldl 67 | override CFLAGS += -Wall -Wextra -Werror 68 | override CXXFLAGS += -Wall -Wextra -Werror -Wno-missing-field-initializers 69 | 70 | override IFACE_DIR := ../interface 71 | override BINARY := qndb 72 | # cli sources 73 | override SOURCES := qndb.cc ndb_cli.cc $(IFACE_DIR)/ndb_proxy.cpp 74 | 75 | override MOCS := $(IFACE_DIR)/ndb_proxy.h ndb_cli.h 76 | 77 | override OBJECTS_C := $(filter %.o,$(SOURCES:%.c=%.o)) 78 | override OBJECTS_CXX := $(filter %.o,$(SOURCES:%.cc=%.o)) 79 | override OBJECTS_CXX1 := $(filter %.o,$(SOURCES:%.cpp=%.o)) 80 | override MOCS_MOC := $(filter %.moc,$(MOCS:%.h=%.moc)) 81 | override OBJECTS_MOC := $(MOCS_MOC:%=%.o) 82 | override GENERATED := $(BINARY) $(OBJECTS_C) $(OBJECTS_CXX) $(OBJECTS_CXX1) $(MOCS_MOC) $(OBJECTS_MOC) 83 | 84 | override GITIGNORE += .kdev4/ *.kdev4 .kateconfig .vscode/ .idea/ .clangd/ .cache/ compile_commands.json $(filter-out ../interface/%,$(GENERATED)) 85 | 86 | $(BINARY): override CFLAGS += -fPIC 87 | $(BINARY): override CXXFLAGS += -fPIC 88 | 89 | override nh_cmd_bin = $(CXX) $(CPPFLAGS) $(CXXFLAGS) -o $(1) $(2) $(LDFLAGS) 90 | override nh_cmd_c = $(CC) $(CPPFLAGS) $(CFLAGS) -c $(2) -o $(1) 91 | override nh_cmd_cc = $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(2) -o $(1) 92 | override nh_cmd_moco = $(CXX) -xc++ $(CPPFLAGS) $(CXXFLAGS) -c $(2) -o $(1) 93 | override nh_cmd_moch = $(MOC) $(2) -o $(1) 94 | 95 | 96 | $(BINARY): $(OBJECTS_CXX) $(OBJECTS_CXX1) $(OBJECTS_MOC) 97 | $(call nh_cmd_bin,$@,$^) 98 | $(OBJECTS_C): %.o: %.c 99 | $(call nh_cmd_c,$@,$^) 100 | $(OBJECTS_CXX): %.o: %.cc 101 | $(call nh_cmd_cc,$@,$^) 102 | $(OBJECTS_CXX1): %.o: %.cpp 103 | $(call nh_cmd_cc,$@,$^) 104 | $(OBJECTS_MOC): %.moc.o: %.moc 105 | $(call nh_cmd_moco,$@,$^) 106 | $(MOCS_MOC): %.moc: %.h 107 | $(call nh_cmd_moch,$@,$^) 108 | 109 | .PHONY: all clean gitignore 110 | 111 | all: $(BINARY) 112 | 113 | clean: 114 | rm -f $(GENERATED) 115 | 116 | gitignore: 117 | echo "# make gitignore" > .gitignore 118 | echo "$(strip $(GITIGNORE))" | tr " " "\n" >> .gitignore 119 | -------------------------------------------------------------------------------- /src/cli/ndb_cli.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | #include "ndb_cli.h" 12 | 13 | MethodParamList::MethodParamList() { 14 | mp.resize(10); 15 | } 16 | 17 | MethodParamList::~MethodParamList() { 18 | for (int i = 0; i < mp.size(); ++i) { 19 | if (mp[i].param) { 20 | QMetaType::destroy(mp[i].type, mp[i].param); 21 | } 22 | } 23 | } 24 | 25 | NDBCli::NDBCli(QObject* parent, com::github::shermp::nickeldbus *ndb) : QObject(parent) { 26 | this->ndb = ndb; 27 | signalComplete = methodComplete = false; 28 | methodName = QString(); 29 | methodArgs = QStringList(); 30 | signalNames = QStringList(); 31 | timeout = -1; 32 | } 33 | 34 | int NDBCli::getMethodIndex() { 35 | const QMetaObject *mo = ndb->metaObject(); 36 | for (int i = mo->methodOffset(); i < mo->methodCount(); ++i ) { 37 | QMetaMethod method = mo->method(i); 38 | if (!QString(method.name()).compare(methodName) && (method.methodType() == QMetaMethod::Method || method.methodType() == QMetaMethod::Slot)) { 39 | if (method.parameterCount() == methodArgs.size()) { 40 | return i; 41 | } 42 | } 43 | } 44 | return -1; 45 | } 46 | 47 | bool NDBCli::convertParam(int index, int typeID, void *param) { 48 | bool ok = false; 49 | 50 | if (typeID == QMetaType::Type::Int) { 51 | int *i = reinterpret_cast (param); 52 | *i = methodArgs.at(index).toInt(&ok); 53 | 54 | } else if (typeID == QMetaType::Type::Bool) { 55 | bool *b = reinterpret_cast (param); 56 | ok = true; 57 | if (!methodArgs.at(index).compare("true", Qt::CaseInsensitive) || !methodArgs.at(index).compare("t", Qt::CaseInsensitive)) { 58 | *b = true; 59 | } else if (!methodArgs.at(index).compare("false", Qt::CaseInsensitive) || !methodArgs.at(index).compare("f", Qt::CaseInsensitive)) { 60 | *b = false; 61 | } else { 62 | ok = false; 63 | } 64 | 65 | } else if (typeID == QMetaType::Type::QString) { 66 | QString *s = reinterpret_cast (param); 67 | s->append(methodArgs.at(index)); 68 | ok = true; 69 | 70 | } else { 71 | ok = false; 72 | } 73 | return ok; 74 | } 75 | 76 | template 77 | int NDBCli::printMethodReply(void *reply) { 78 | int rv = -1; 79 | QDBusPendingReply *r = reinterpret_cast*>(reply); 80 | r->waitForFinished(); 81 | if (!r->isError()) { 82 | if (r->count() > 0) { 83 | QTextStream(stdout) << r->value() << endl; 84 | } 85 | rv = 0; 86 | } else { 87 | errString = QString("method failed with err: %1 and message: %2").arg(QDBusError::errorString(r->error().type())).arg(r->error().message()); 88 | } 89 | return rv; 90 | } 91 | 92 | // We seem to need to make this a separate function from above, as the compiler 93 | // throws a fit when typename parameter is void. 94 | int NDBCli::printMethodReply(void *reply) { 95 | int rv = -0; 96 | QDBusPendingReply<> *r = reinterpret_cast*>(reply); 97 | r->waitForFinished(); 98 | if (r->isError()) { 99 | errString = QString("method failed with err: %1 and message: %2").arg(QDBusError::errorString(r->error().type())).arg(r->error().message()); 100 | rv = -1; 101 | } 102 | return rv; 103 | } 104 | 105 | int NDBCli::callMethodInvoke() { 106 | int methodIndex = getMethodIndex(); 107 | if (methodIndex < 0) { 108 | errString = QStringLiteral("non-existent method or invalid parameter count"); 109 | return -1; 110 | } 111 | QMetaMethod m = ndb->metaObject()->method(methodIndex); 112 | if (m.parameterCount() > 10) { 113 | errString = QStringLiteral("a maximum of 10 parameters are allowed"); 114 | return -1; 115 | } 116 | MethodParamList params = MethodParamList(); 117 | for (int i = 0; i < m.parameterCount(); ++i) { 118 | params.mp[i].type = m.parameterType(i); 119 | params.mp[i].param = QMetaType::create(params.mp[i].type); 120 | if (!convertParam(i, params.mp[i].type, params.mp[i].param)) { 121 | errString = QString("unable to convert parameter %1").arg(QString(m.parameterNames().at(i))); 122 | return -1; 123 | } 124 | params.mp[i].genericArg = QGenericArgument(m.parameterNames().at(i), params.mp[i].param); 125 | } 126 | // QDBusPendingReply<> doesn't appear to be a QObject, and even if it is, it 127 | // isn't registered as a QMetaType. We'll take care of it here, and register 128 | // one of every type we may currently encounter (plus int, because it could 129 | // be used in the future). 130 | int voidPR = qRegisterMetaType>("QDBusPendingReply<>"); 131 | int strPR = qRegisterMetaType>("QDBusPendingReply"); 132 | int boolPR = qRegisterMetaType>("QDBusPendingReply"); 133 | int intPR = qRegisterMetaType>("QDBusPendingReply"); 134 | int id = QMetaType::type(m.typeName()); 135 | if (id == QMetaType::UnknownType) { 136 | errString = QStringLiteral("could not create variable of unknown type"); 137 | return -1; 138 | } 139 | void *ret = QMetaType::create(id); 140 | if (!ret) { 141 | errString = QStringLiteral("unable to create return variable"); 142 | return -1; 143 | } 144 | if (!m.invoke(ndb, 145 | Qt::DirectConnection, 146 | QGenericReturnArgument(m.typeName(), ret), 147 | params.mp[0].genericArg, params.mp[1].genericArg, params.mp[2].genericArg, params.mp[3].genericArg, params.mp[4].genericArg, 148 | params.mp[5].genericArg, params.mp[6].genericArg, params.mp[7].genericArg, params.mp[8].genericArg, params.mp[9].genericArg 149 | )) { 150 | errString = QString("unable to call method %1").arg(QString(m.methodSignature())); 151 | QMetaType::destroy(id, ret); 152 | return -1; 153 | } 154 | // Stupid templated class. Is there a way of making the following more generic? 155 | int printRV; 156 | if (id == voidPR) {printRV = printMethodReply(ret);} 157 | else if (id == strPR) {printRV = printMethodReply(ret);} 158 | else if (id == boolPR) {printRV = printMethodReply(ret);} 159 | else if (id == intPR) {printRV = printMethodReply(ret);} 160 | else {printRV = -1;} 161 | QMetaType::destroy(id, ret); 162 | return printRV; 163 | } 164 | 165 | #define NDBCLI_SIG_NAME() QString(sender()->metaObject()->method(senderSignalIndex()).name()) 166 | #define NDBCLI_SIG_CONNECT(signal, handler) QObject::connect(ndb, &NDBProxy::signal, this, &NDBCli::handler) 167 | 168 | void NDBCli::connectSignals() { 169 | NDBCLI_SIG_CONNECT(dlgConfirmResult, handleSignalParam1); 170 | NDBCLI_SIG_CONNECT(dlgConfirmTextInput, handleSignalParam1); 171 | NDBCLI_SIG_CONNECT(pfmAboutToConnect, handleSignalParam0); 172 | NDBCLI_SIG_CONNECT(pfmDoneProcessing, handleSignalParam0); 173 | NDBCLI_SIG_CONNECT(fssFinished, handleSignalParam0); 174 | NDBCLI_SIG_CONNECT(fssGotNumFilesToProcess, handleSignalParam1); 175 | NDBCLI_SIG_CONNECT(fssParseProgress, handleSignalParam1); 176 | NDBCLI_SIG_CONNECT(wmLinkQualityForConnectedNetwork, handleSignalParam1); 177 | NDBCLI_SIG_CONNECT(wmMacAddressAvailable, handleSignalParam1); 178 | NDBCLI_SIG_CONNECT(wmNetworkConnected, handleSignalParam0); 179 | NDBCLI_SIG_CONNECT(wmNetworkDisconnected, handleSignalParam0); 180 | NDBCLI_SIG_CONNECT(wmNetworkFailedToConnect, handleSignalParam0); 181 | NDBCLI_SIG_CONNECT(wmNetworkForgotten, handleSignalParam0); 182 | NDBCLI_SIG_CONNECT(wmScanningAborted, handleSignalParam0); 183 | NDBCLI_SIG_CONNECT(wmScanningFinished, handleSignalParam0); 184 | NDBCLI_SIG_CONNECT(wmScanningStarted, handleSignalParam0); 185 | NDBCLI_SIG_CONNECT(wmTryingToConnect, handleSignalParam0); 186 | NDBCLI_SIG_CONNECT(wmWifiEnabled, handleSignalParam1); 187 | NDBCLI_SIG_CONNECT(ndbViewChanged, handleSignalParam1); 188 | NDBCLI_SIG_CONNECT(rvPageChanged, handleSignalParam1); 189 | } 190 | 191 | void NDBCli::handleSignalParam0() { 192 | handleSignal(NDBCLI_SIG_NAME()); 193 | } 194 | 195 | void NDBCli::handleSignalParam1(QVariant val1) { 196 | handleSignal(NDBCLI_SIG_NAME(), val1); 197 | } 198 | 199 | void NDBCli::handleSignalParam2(QVariant val1, QVariant val2) { 200 | handleSignal(NDBCLI_SIG_NAME(), val1, val2); 201 | } 202 | 203 | void NDBCli::handleSignal(const QString& sigName, QVariant val1, QVariant val2, QVariant val3, QVariant val4) { 204 | if (signalNames.contains(sigName)) { 205 | QTextStream out(stdout); 206 | out << sigName; 207 | if (val1.isValid()) { out << " " << val1.toString(); } 208 | if (val2.isValid()) { out << " " << val2.toString(); } 209 | if (val3.isValid()) { out << " " << val3.toString(); } 210 | if (val4.isValid()) { out << " " << val4.toString(); } 211 | out << endl; 212 | if (methodName.isEmpty() || methodComplete) { 213 | QCoreApplication::quit(); 214 | } else { 215 | signalComplete = true; 216 | } 217 | } 218 | } 219 | 220 | void NDBCli::handleTimeout() { 221 | qCritical() << "timeout expired after" << timeout << "milliseconds"; 222 | QCoreApplication::exit(1); 223 | } 224 | 225 | void NDBCli::setMethodName(QString name) { 226 | methodName = name; 227 | } 228 | 229 | void NDBCli::setMethodArgs(QStringList args) { 230 | methodArgs = args; 231 | } 232 | 233 | void NDBCli::setSignalNames(QStringList names) { 234 | signalNames = names; 235 | } 236 | 237 | void NDBCli::setTimeout(int t) { 238 | timeout = t; 239 | } 240 | 241 | void NDBCli::setPrintAPI(bool api) { 242 | printApi = api; 243 | } 244 | 245 | void NDBCli::printMethods(int methodType) { 246 | QTextStream methodOut(stdout); 247 | const QMetaObject *mo = ndb->metaObject(); 248 | for (int i = mo->methodOffset(); i < mo->methodCount(); ++ i) { 249 | QMetaMethod method = mo->method(i); 250 | if (method.methodType() == methodType) { 251 | methodOut << " " << method.name(); 252 | auto params = method.parameterNames(); 253 | auto paramTypes = method.parameterTypes(); 254 | for (int j = 0; j < params.size(); ++j) { 255 | methodOut << " " << "<" << paramTypes.at(j) << ">" << " " << params.at(j); 256 | if (j < params.size() - 1) { 257 | methodOut << ","; 258 | } 259 | } 260 | methodOut << endl; 261 | } 262 | } 263 | } 264 | 265 | void NDBCli::printAPI() { 266 | QTextStream(stdout) << "The following methods and their arguments can be called:" << endl; 267 | printMethods(QMetaMethod::Slot); 268 | QTextStream(stdout) << "\nThe following signals and their 'return' value can be waited for:" << endl; 269 | printMethods(QMetaMethod::Signal); 270 | } 271 | 272 | void NDBCli::start() { 273 | if (!ndb->isValid()) { 274 | qCritical() << "interface not valid"; 275 | QCoreApplication::exit(1); 276 | } 277 | if (printApi) { 278 | printAPI(); 279 | QCoreApplication::quit(); 280 | } 281 | if (signalNames.size() > 0) { 282 | connectSignals(); 283 | } 284 | if (!methodName.isEmpty()) { 285 | if (callMethodInvoke() != 0) { 286 | qCritical() << "failed with: " << errString; 287 | QCoreApplication::exit(1); 288 | } else { 289 | if (signalNames.size() > 0 && signalComplete) { 290 | QCoreApplication::quit(); 291 | } else if (signalNames.size() == 0) { 292 | QCoreApplication::quit(); 293 | } else { 294 | methodComplete = true; 295 | } 296 | } 297 | } 298 | if (timeout > 0) { 299 | QTimer::singleShot(timeout, this, SLOT(handleTimeout())); 300 | } 301 | } 302 | -------------------------------------------------------------------------------- /src/cli/ndb_cli.h: -------------------------------------------------------------------------------- 1 | #ifndef NICKEL_DBUS_CLI_H 2 | #define NICKEL_DBUS_CLI_H 3 | 4 | #include 5 | #include 6 | #include "../interface/ndb_proxy.h" 7 | 8 | struct MethodParamList { 9 | struct MethodParam { 10 | int type; 11 | void *param; 12 | QGenericArgument genericArg; 13 | }; 14 | QVector mp; 15 | MethodParamList(); 16 | ~MethodParamList(); 17 | }; 18 | 19 | class NDBCli : public QObject { 20 | Q_OBJECT 21 | 22 | public: 23 | NDBCli(QObject* parent, com::github::shermp::nickeldbus* ndb); 24 | 25 | void setMethodName(QString name); 26 | void setMethodArgs(QStringList args); 27 | void setSignalNames(QStringList names); 28 | void setTimeout(int timeout); 29 | void setPrintAPI(bool api); 30 | void handleSignalParam0(); 31 | void handleSignalParam1(QVariant val1); 32 | void handleSignalParam2(QVariant val1, QVariant val2); 33 | Q_SIGNALS: 34 | void timeoutTriggered(); 35 | public Q_SLOTS: 36 | void start(); 37 | void handleTimeout(); 38 | private: 39 | QString errString; 40 | QString methodName; 41 | QStringList methodArgs; 42 | QStringList signalNames; 43 | bool signalComplete, methodComplete, printApi; 44 | int timeout; 45 | com::github::shermp::nickeldbus* ndb; 46 | int callMethodInvoke(); 47 | template 48 | int printMethodReply(void *reply); 49 | int printMethodReply(void *reply); 50 | bool convertParam(int index, int typeID, void *param); 51 | int getMethodIndex(); 52 | void connectSignals(); 53 | void printMethods(int methodType); 54 | void printAPI(); 55 | void handleSignal(const QString& sigName, QVariant = QVariant(), QVariant = QVariant(), QVariant = QVariant(), QVariant = QVariant()); 56 | }; 57 | 58 | #endif 59 | -------------------------------------------------------------------------------- /src/cli/qndb.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "ndb_cli.h" 6 | 7 | int main(int argc, char **argv) { 8 | QCoreApplication app(argc, argv); 9 | QCoreApplication::setApplicationName("qndb"); 10 | QCoreApplication::setApplicationVersion("0.1"); 11 | 12 | QCommandLineParser parser; 13 | parser.setApplicationDescription("Qt CLI for NickelDBus"); 14 | parser.addHelpOption(); 15 | parser.addVersionOption(); 16 | 17 | parser.addPositionalArgument("arguments", "Arguments to pass to method. Have no affect when a method is not set.", "[args...]"); 18 | 19 | QCommandLineOption signalOption(QStringList() << "s" << "signal", "Wait for signal, and prints its output, if any.", "signal name"); 20 | QCommandLineOption timeoutOption(QStringList() << "t" << "timeout", "Signal timeout in milliseconds.", "timeout ms"); 21 | QCommandLineOption methodOption(QStringList() << "m" << "method", "Method to invoke.", "method name"); 22 | QCommandLineOption apiOption(QStringList() << "a" << "api", "Print API usage"); 23 | parser.addOption(signalOption); 24 | parser.addOption(timeoutOption); 25 | parser.addOption(methodOption); 26 | parser.addOption(apiOption); 27 | 28 | parser.process(app); 29 | 30 | const QStringList methodArgs = parser.positionalArguments(); 31 | 32 | com::github::shermp::nickeldbus ndb("com.github.shermp.nickeldbus", "/nickeldbus", QDBusConnection::systemBus(), &app); 33 | NDBCli cli(&app, &ndb); 34 | 35 | cli.setPrintAPI(parser.isSet(apiOption)); 36 | if (parser.isSet(signalOption)) { 37 | cli.setSignalNames(parser.values(signalOption)); 38 | } 39 | if (parser.isSet(methodOption)) { 40 | cli.setMethodName(parser.value(methodOption)); 41 | } 42 | if (parser.isSet(timeoutOption)) { 43 | int timeout = -1; 44 | bool timeout_ok; 45 | timeout = parser.value(timeoutOption).toInt(&timeout_ok); 46 | if (timeout_ok) { 47 | cli.setTimeout(timeout); 48 | } 49 | } 50 | cli.setMethodArgs(parser.positionalArguments()); 51 | 52 | QTimer::singleShot(0, &cli, SLOT(start())); 53 | return app.exec(); 54 | } 55 | -------------------------------------------------------------------------------- /src/interface/com.github.shermp.nickeldbus.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | -------------------------------------------------------------------------------- /src/interface/ndb_adapter.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file was generated by qdbusxml2cpp version 0.8 3 | * Command line was: qdbusxml2cpp -c NDBAdapter -a ndb_adapter com.github.shermp.nickeldbus.xml 4 | * 5 | * qdbusxml2cpp is Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). 6 | * 7 | * This is an auto-generated file. 8 | * Do not edit! All changes made to it will be lost. 9 | */ 10 | 11 | #include "ndb_adapter.h" 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | /* 21 | * Implementation of adaptor class NDBAdapter 22 | */ 23 | 24 | NDBAdapter::NDBAdapter(QObject *parent) 25 | : QDBusAbstractAdaptor(parent) 26 | { 27 | // constructor 28 | setAutoRelaySignals(true); 29 | } 30 | 31 | NDBAdapter::~NDBAdapter() 32 | { 33 | // destructor 34 | } 35 | 36 | void NDBAdapter::bwmOpenBrowser() 37 | { 38 | // handle method call com.github.shermp.nickeldbus.bwmOpenBrowser 39 | QMetaObject::invokeMethod(parent(), "bwmOpenBrowser"); 40 | } 41 | 42 | void NDBAdapter::bwmOpenBrowser(bool modal) 43 | { 44 | // handle method call com.github.shermp.nickeldbus.bwmOpenBrowser 45 | QMetaObject::invokeMethod(parent(), "bwmOpenBrowser", Q_ARG(bool, modal)); 46 | } 47 | 48 | void NDBAdapter::bwmOpenBrowser(bool modal, const QString &url) 49 | { 50 | // handle method call com.github.shermp.nickeldbus.bwmOpenBrowser 51 | QMetaObject::invokeMethod(parent(), "bwmOpenBrowser", Q_ARG(bool, modal), Q_ARG(QString, url)); 52 | } 53 | 54 | void NDBAdapter::bwmOpenBrowser(bool modal, const QString &url, const QString &css) 55 | { 56 | // handle method call com.github.shermp.nickeldbus.bwmOpenBrowser 57 | QMetaObject::invokeMethod(parent(), "bwmOpenBrowser", Q_ARG(bool, modal), Q_ARG(QString, url), Q_ARG(QString, css)); 58 | } 59 | 60 | void NDBAdapter::dlgConfirmAccept(const QString &title, const QString &body, const QString &acceptText) 61 | { 62 | // handle method call com.github.shermp.nickeldbus.dlgConfirmAccept 63 | QMetaObject::invokeMethod(parent(), "dlgConfirmAccept", Q_ARG(QString, title), Q_ARG(QString, body), Q_ARG(QString, acceptText)); 64 | } 65 | 66 | void NDBAdapter::dlgConfirmAcceptReject(const QString &title, const QString &body, const QString &acceptText, const QString &rejectText) 67 | { 68 | // handle method call com.github.shermp.nickeldbus.dlgConfirmAcceptReject 69 | QMetaObject::invokeMethod(parent(), "dlgConfirmAcceptReject", Q_ARG(QString, title), Q_ARG(QString, body), Q_ARG(QString, acceptText), Q_ARG(QString, rejectText)); 70 | } 71 | 72 | void NDBAdapter::dlgConfirmClose() 73 | { 74 | // handle method call com.github.shermp.nickeldbus.dlgConfirmClose 75 | QMetaObject::invokeMethod(parent(), "dlgConfirmClose"); 76 | } 77 | 78 | void NDBAdapter::dlgConfirmCreate() 79 | { 80 | // handle method call com.github.shermp.nickeldbus.dlgConfirmCreate 81 | QMetaObject::invokeMethod(parent(), "dlgConfirmCreate"); 82 | } 83 | 84 | void NDBAdapter::dlgConfirmCreate(bool createLineEdit) 85 | { 86 | // handle method call com.github.shermp.nickeldbus.dlgConfirmCreate 87 | QMetaObject::invokeMethod(parent(), "dlgConfirmCreate", Q_ARG(bool, createLineEdit)); 88 | } 89 | 90 | void NDBAdapter::dlgConfirmNoBtn(const QString &title, const QString &body) 91 | { 92 | // handle method call com.github.shermp.nickeldbus.dlgConfirmNoBtn 93 | QMetaObject::invokeMethod(parent(), "dlgConfirmNoBtn", Q_ARG(QString, title), Q_ARG(QString, body)); 94 | } 95 | 96 | void NDBAdapter::dlgConfirmReject(const QString &title, const QString &body, const QString &rejectText) 97 | { 98 | // handle method call com.github.shermp.nickeldbus.dlgConfirmReject 99 | QMetaObject::invokeMethod(parent(), "dlgConfirmReject", Q_ARG(QString, title), Q_ARG(QString, body), Q_ARG(QString, rejectText)); 100 | } 101 | 102 | void NDBAdapter::dlgConfirmSetAccept(const QString &acceptText) 103 | { 104 | // handle method call com.github.shermp.nickeldbus.dlgConfirmSetAccept 105 | QMetaObject::invokeMethod(parent(), "dlgConfirmSetAccept", Q_ARG(QString, acceptText)); 106 | } 107 | 108 | void NDBAdapter::dlgConfirmSetBody(const QString &body) 109 | { 110 | // handle method call com.github.shermp.nickeldbus.dlgConfirmSetBody 111 | QMetaObject::invokeMethod(parent(), "dlgConfirmSetBody", Q_ARG(QString, body)); 112 | } 113 | 114 | void NDBAdapter::dlgConfirmSetLEPassword(bool password) 115 | { 116 | // handle method call com.github.shermp.nickeldbus.dlgConfirmSetLEPassword 117 | QMetaObject::invokeMethod(parent(), "dlgConfirmSetLEPassword", Q_ARG(bool, password)); 118 | } 119 | 120 | void NDBAdapter::dlgConfirmSetLEPlaceholder(const QString &placeholder) 121 | { 122 | // handle method call com.github.shermp.nickeldbus.dlgConfirmSetLEPlaceholder 123 | QMetaObject::invokeMethod(parent(), "dlgConfirmSetLEPlaceholder", Q_ARG(QString, placeholder)); 124 | } 125 | 126 | void NDBAdapter::dlgConfirmSetModal(bool modal) 127 | { 128 | // handle method call com.github.shermp.nickeldbus.dlgConfirmSetModal 129 | QMetaObject::invokeMethod(parent(), "dlgConfirmSetModal", Q_ARG(bool, modal)); 130 | } 131 | 132 | void NDBAdapter::dlgConfirmSetProgress(int min, int max, int val) 133 | { 134 | // handle method call com.github.shermp.nickeldbus.dlgConfirmSetProgress 135 | QMetaObject::invokeMethod(parent(), "dlgConfirmSetProgress", Q_ARG(int, min), Q_ARG(int, max), Q_ARG(int, val)); 136 | } 137 | 138 | void NDBAdapter::dlgConfirmSetProgress(int min, int max, int val, const QString &format) 139 | { 140 | // handle method call com.github.shermp.nickeldbus.dlgConfirmSetProgress 141 | QMetaObject::invokeMethod(parent(), "dlgConfirmSetProgress", Q_ARG(int, min), Q_ARG(int, max), Q_ARG(int, val), Q_ARG(QString, format)); 142 | } 143 | 144 | void NDBAdapter::dlgConfirmSetReject(const QString &rejectText) 145 | { 146 | // handle method call com.github.shermp.nickeldbus.dlgConfirmSetReject 147 | QMetaObject::invokeMethod(parent(), "dlgConfirmSetReject", Q_ARG(QString, rejectText)); 148 | } 149 | 150 | void NDBAdapter::dlgConfirmSetTitle(const QString &title) 151 | { 152 | // handle method call com.github.shermp.nickeldbus.dlgConfirmSetTitle 153 | QMetaObject::invokeMethod(parent(), "dlgConfirmSetTitle", Q_ARG(QString, title)); 154 | } 155 | 156 | void NDBAdapter::dlgConfirmShow() 157 | { 158 | // handle method call com.github.shermp.nickeldbus.dlgConfirmShow 159 | QMetaObject::invokeMethod(parent(), "dlgConfirmShow"); 160 | } 161 | 162 | void NDBAdapter::dlgConfirmShowClose(bool show) 163 | { 164 | // handle method call com.github.shermp.nickeldbus.dlgConfirmShowClose 165 | QMetaObject::invokeMethod(parent(), "dlgConfirmShowClose", Q_ARG(bool, show)); 166 | } 167 | 168 | QString NDBAdapter::imgSizeForType(const QString &type) 169 | { 170 | // handle method call com.github.shermp.nickeldbus.imgSizeForType 171 | QString out0; 172 | QMetaObject::invokeMethod(parent(), "imgSizeForType", Q_RETURN_ARG(QString, out0), Q_ARG(QString, type)); 173 | return out0; 174 | } 175 | 176 | void NDBAdapter::mwcHome() 177 | { 178 | // handle method call com.github.shermp.nickeldbus.mwcHome 179 | QMetaObject::invokeMethod(parent(), "mwcHome"); 180 | } 181 | 182 | void NDBAdapter::mwcToast(int toastDuration, const QString &msgMain) 183 | { 184 | // handle method call com.github.shermp.nickeldbus.mwcToast 185 | QMetaObject::invokeMethod(parent(), "mwcToast", Q_ARG(int, toastDuration), Q_ARG(QString, msgMain)); 186 | } 187 | 188 | void NDBAdapter::mwcToast(int toastDuration, const QString &msgMain, const QString &msgSub) 189 | { 190 | // handle method call com.github.shermp.nickeldbus.mwcToast 191 | QMetaObject::invokeMethod(parent(), "mwcToast", Q_ARG(int, toastDuration), Q_ARG(QString, msgMain), Q_ARG(QString, msgSub)); 192 | } 193 | 194 | void NDBAdapter::n3fssSyncBoth() 195 | { 196 | // handle method call com.github.shermp.nickeldbus.n3fssSyncBoth 197 | QMetaObject::invokeMethod(parent(), "n3fssSyncBoth"); 198 | } 199 | 200 | void NDBAdapter::n3fssSyncOnboard() 201 | { 202 | // handle method call com.github.shermp.nickeldbus.n3fssSyncOnboard 203 | QMetaObject::invokeMethod(parent(), "n3fssSyncOnboard"); 204 | } 205 | 206 | void NDBAdapter::n3fssSyncSD() 207 | { 208 | // handle method call com.github.shermp.nickeldbus.n3fssSyncSD 209 | QMetaObject::invokeMethod(parent(), "n3fssSyncSD"); 210 | } 211 | 212 | QString NDBAdapter::ndbCurrentView() 213 | { 214 | // handle method call com.github.shermp.nickeldbus.ndbCurrentView 215 | QString out0; 216 | QMetaObject::invokeMethod(parent(), "ndbCurrentView", Q_RETURN_ARG(QString, out0)); 217 | return out0; 218 | } 219 | 220 | QString NDBAdapter::ndbFirmwareVersion() 221 | { 222 | // handle method call com.github.shermp.nickeldbus.ndbFirmwareVersion 223 | QString out0; 224 | QMetaObject::invokeMethod(parent(), "ndbFirmwareVersion", Q_RETURN_ARG(QString, out0)); 225 | return out0; 226 | } 227 | 228 | QString NDBAdapter::ndbNickelClassDetails(const QString &staticMmetaobjectSymbol) 229 | { 230 | // handle method call com.github.shermp.nickeldbus.ndbNickelClassDetails 231 | QString out0; 232 | QMetaObject::invokeMethod(parent(), "ndbNickelClassDetails", Q_RETURN_ARG(QString, out0), Q_ARG(QString, staticMmetaobjectSymbol)); 233 | return out0; 234 | } 235 | 236 | QString NDBAdapter::ndbNickelWidgets() 237 | { 238 | // handle method call com.github.shermp.nickeldbus.ndbNickelWidgets 239 | QString out0; 240 | QMetaObject::invokeMethod(parent(), "ndbNickelWidgets", Q_RETURN_ARG(QString, out0)); 241 | return out0; 242 | } 243 | 244 | bool NDBAdapter::ndbSignalConnected(const QString &signalName) 245 | { 246 | // handle method call com.github.shermp.nickeldbus.ndbSignalConnected 247 | bool out0; 248 | QMetaObject::invokeMethod(parent(), "ndbSignalConnected", Q_RETURN_ARG(bool, out0), Q_ARG(QString, signalName)); 249 | return out0; 250 | } 251 | 252 | QString NDBAdapter::ndbVersion() 253 | { 254 | // handle method call com.github.shermp.nickeldbus.ndbVersion 255 | QString out0; 256 | QMetaObject::invokeMethod(parent(), "ndbVersion", Q_RETURN_ARG(QString, out0)); 257 | return out0; 258 | } 259 | 260 | void NDBAdapter::ndbWifiKeepalive(bool keepalive) 261 | { 262 | // handle method call com.github.shermp.nickeldbus.ndbWifiKeepalive 263 | QMetaObject::invokeMethod(parent(), "ndbWifiKeepalive", Q_ARG(bool, keepalive)); 264 | } 265 | 266 | void NDBAdapter::nsAutoUSBGadget(const QString &action) 267 | { 268 | // handle method call com.github.shermp.nickeldbus.nsAutoUSBGadget 269 | QMetaObject::invokeMethod(parent(), "nsAutoUSBGadget", Q_ARG(QString, action)); 270 | } 271 | 272 | void NDBAdapter::nsDarkMode(const QString &action) 273 | { 274 | // handle method call com.github.shermp.nickeldbus.nsDarkMode 275 | QMetaObject::invokeMethod(parent(), "nsDarkMode", Q_ARG(QString, action)); 276 | } 277 | 278 | void NDBAdapter::nsForceWifi(const QString &action) 279 | { 280 | // handle method call com.github.shermp.nickeldbus.nsForceWifi 281 | QMetaObject::invokeMethod(parent(), "nsForceWifi", Q_ARG(QString, action)); 282 | } 283 | 284 | void NDBAdapter::nsInvert(const QString &action) 285 | { 286 | // handle method call com.github.shermp.nickeldbus.nsInvert 287 | QMetaObject::invokeMethod(parent(), "nsInvert", Q_ARG(QString, action)); 288 | } 289 | 290 | void NDBAdapter::nsLockscreen(const QString &action) 291 | { 292 | // handle method call com.github.shermp.nickeldbus.nsLockscreen 293 | QMetaObject::invokeMethod(parent(), "nsLockscreen", Q_ARG(QString, action)); 294 | } 295 | 296 | void NDBAdapter::nsScreenshots(const QString &action) 297 | { 298 | // handle method call com.github.shermp.nickeldbus.nsScreenshots 299 | QMetaObject::invokeMethod(parent(), "nsScreenshots", Q_ARG(QString, action)); 300 | } 301 | 302 | void NDBAdapter::pfmRescanBooks() 303 | { 304 | // handle method call com.github.shermp.nickeldbus.pfmRescanBooks 305 | QMetaObject::invokeMethod(parent(), "pfmRescanBooks"); 306 | } 307 | 308 | void NDBAdapter::pfmRescanBooksFull() 309 | { 310 | // handle method call com.github.shermp.nickeldbus.pfmRescanBooksFull 311 | QMetaObject::invokeMethod(parent(), "pfmRescanBooksFull"); 312 | } 313 | 314 | void NDBAdapter::pwrReboot() 315 | { 316 | // handle method call com.github.shermp.nickeldbus.pwrReboot 317 | QMetaObject::invokeMethod(parent(), "pwrReboot"); 318 | } 319 | 320 | void NDBAdapter::pwrShutdown() 321 | { 322 | // handle method call com.github.shermp.nickeldbus.pwrShutdown 323 | QMetaObject::invokeMethod(parent(), "pwrShutdown"); 324 | } 325 | 326 | void NDBAdapter::pwrSleep() 327 | { 328 | // handle method call com.github.shermp.nickeldbus.pwrSleep 329 | QMetaObject::invokeMethod(parent(), "pwrSleep"); 330 | } 331 | 332 | void NDBAdapter::wfmConnectWireless() 333 | { 334 | // handle method call com.github.shermp.nickeldbus.wfmConnectWireless 335 | QMetaObject::invokeMethod(parent(), "wfmConnectWireless"); 336 | } 337 | 338 | void NDBAdapter::wfmConnectWirelessSilently() 339 | { 340 | // handle method call com.github.shermp.nickeldbus.wfmConnectWirelessSilently 341 | QMetaObject::invokeMethod(parent(), "wfmConnectWirelessSilently"); 342 | } 343 | 344 | void NDBAdapter::wfmSetAirplaneMode(const QString &action) 345 | { 346 | // handle method call com.github.shermp.nickeldbus.wfmSetAirplaneMode 347 | QMetaObject::invokeMethod(parent(), "wfmSetAirplaneMode", Q_ARG(QString, action)); 348 | } 349 | 350 | -------------------------------------------------------------------------------- /src/interface/ndb_adapter.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file was generated by qdbusxml2cpp version 0.8 3 | * Command line was: qdbusxml2cpp -c NDBAdapter -a ndb_adapter com.github.shermp.nickeldbus.xml 4 | * 5 | * qdbusxml2cpp is Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). 6 | * 7 | * This is an auto-generated file. 8 | * This file may have been hand-edited. Look for HAND-EDIT comments 9 | * before re-generating it. 10 | */ 11 | 12 | #ifndef NDB_ADAPTER_H_1714266534 13 | #define NDB_ADAPTER_H_1714266534 14 | 15 | #include 16 | #include 17 | QT_BEGIN_NAMESPACE 18 | class QByteArray; 19 | template class QList; 20 | template class QMap; 21 | class QString; 22 | class QStringList; 23 | class QVariant; 24 | QT_END_NAMESPACE 25 | 26 | /* 27 | * Adaptor class for interface com.github.shermp.nickeldbus 28 | */ 29 | class NDBAdapter: public QDBusAbstractAdaptor 30 | { 31 | Q_OBJECT 32 | Q_CLASSINFO("D-Bus Interface", "com.github.shermp.nickeldbus") 33 | Q_CLASSINFO("D-Bus Introspection", "" 34 | " \n" 35 | " \n" 36 | " \n" 37 | " \n" 38 | " \n" 39 | " \n" 40 | " \n" 41 | " \n" 42 | " \n" 43 | " \n" 44 | " \n" 45 | " \n" 46 | " \n" 47 | " \n" 48 | " \n" 49 | " \n" 50 | " \n" 51 | " \n" 52 | " \n" 53 | " \n" 54 | " \n" 55 | " \n" 56 | " \n" 57 | " \n" 58 | " \n" 59 | " \n" 60 | " \n" 61 | " \n" 62 | " \n" 63 | " \n" 64 | " \n" 65 | " \n" 66 | " \n" 67 | " \n" 68 | " \n" 69 | " \n" 70 | " \n" 71 | " \n" 72 | " \n" 73 | " \n" 74 | " \n" 75 | " \n" 76 | " \n" 77 | " \n" 78 | " \n" 79 | " \n" 80 | " \n" 81 | " \n" 82 | " \n" 83 | " \n" 84 | " \n" 85 | " \n" 86 | " \n" 87 | " \n" 88 | " \n" 89 | " \n" 90 | " \n" 91 | " \n" 92 | " \n" 93 | " \n" 94 | " \n" 95 | " \n" 96 | " \n" 97 | " \n" 98 | " \n" 99 | " \n" 100 | " \n" 101 | " \n" 102 | " \n" 103 | " \n" 104 | " \n" 105 | " \n" 106 | " \n" 107 | " \n" 108 | " \n" 109 | " \n" 110 | " \n" 111 | " \n" 112 | " \n" 113 | " \n" 114 | " \n" 115 | " \n" 116 | " \n" 117 | " \n" 118 | " \n" 119 | " \n" 120 | " \n" 121 | " \n" 122 | " \n" 123 | " \n" 124 | " \n" 125 | " \n" 126 | " \n" 127 | " \n" 128 | " \n" 129 | " \n" 130 | " \n" 131 | " \n" 132 | " \n" 133 | " \n" 134 | " \n" 135 | " \n" 136 | " \n" 137 | " \n" 138 | " \n" 139 | " \n" 140 | " \n" 141 | " \n" 142 | " \n" 143 | " \n" 144 | " \n" 145 | " \n" 146 | " \n" 147 | " \n" 148 | " \n" 149 | " \n" 150 | " \n" 151 | " \n" 152 | " \n" 153 | " \n" 154 | " \n" 155 | " \n" 156 | " \n" 157 | " \n" 158 | " \n" 159 | " \n" 160 | " \n" 161 | " \n" 162 | " \n" 163 | " \n" 164 | " \n" 165 | " \n" 166 | " \n" 167 | " \n" 168 | " \n" 169 | " \n" 170 | " \n" 171 | " \n" 172 | " \n" 173 | " \n" 174 | " \n" 175 | " \n" 176 | " \n" 177 | " \n" 178 | " \n" 179 | " \n" 180 | " \n" 181 | " \n" 182 | " \n" 183 | " \n" 184 | " \n" 185 | " \n" 186 | " \n" 187 | " \n" 188 | " \n" 189 | " \n" 190 | " \n" 191 | " \n" 192 | " \n" 193 | " \n" 194 | " \n" 195 | " \n" 196 | " \n" 197 | " \n" 198 | " \n" 199 | " \n" 200 | " \n" 201 | " \n" 202 | " \n" 203 | " \n" 204 | " \n" 205 | " \n" 206 | " \n" 207 | " \n" 208 | " \n" 209 | " \n" 210 | " \n" 211 | " \n" 212 | " \n" 213 | " \n" 214 | " \n" 215 | " \n" 216 | "") 217 | public: 218 | NDBAdapter(QObject *parent); 219 | virtual ~NDBAdapter(); 220 | 221 | public: // PROPERTIES 222 | public Q_SLOTS: // METHODS 223 | void bwmOpenBrowser(); 224 | void bwmOpenBrowser(bool modal); 225 | void bwmOpenBrowser(bool modal, const QString &url); 226 | void bwmOpenBrowser(bool modal, const QString &url, const QString &css); 227 | void dlgConfirmAccept(const QString &title, const QString &body, const QString &acceptText); 228 | void dlgConfirmAcceptReject(const QString &title, const QString &body, const QString &acceptText, const QString &rejectText); 229 | void dlgConfirmClose(); 230 | void dlgConfirmCreate(); 231 | void dlgConfirmCreate(bool createLineEdit); 232 | void dlgConfirmNoBtn(const QString &title, const QString &body); 233 | void dlgConfirmReject(const QString &title, const QString &body, const QString &rejectText); 234 | void dlgConfirmSetAccept(const QString &acceptText); 235 | void dlgConfirmSetBody(const QString &body); 236 | void dlgConfirmSetLEPassword(bool password); 237 | void dlgConfirmSetLEPlaceholder(const QString &placeholder); 238 | void dlgConfirmSetModal(bool modal); 239 | void dlgConfirmSetProgress(int min, int max, int val); 240 | void dlgConfirmSetProgress(int min, int max, int val, const QString &format); 241 | void dlgConfirmSetReject(const QString &rejectText); 242 | void dlgConfirmSetTitle(const QString &title); 243 | void dlgConfirmShow(); 244 | void dlgConfirmShowClose(bool show); 245 | QString imgSizeForType(const QString &type); 246 | void mwcHome(); 247 | void mwcToast(int toastDuration, const QString &msgMain); 248 | void mwcToast(int toastDuration, const QString &msgMain, const QString &msgSub); 249 | void n3fssSyncBoth(); 250 | void n3fssSyncOnboard(); 251 | void n3fssSyncSD(); 252 | QString ndbCurrentView(); 253 | QString ndbFirmwareVersion(); 254 | QString ndbNickelClassDetails(const QString &staticMmetaobjectSymbol); 255 | QString ndbNickelWidgets(); 256 | bool ndbSignalConnected(const QString &signalName); 257 | QString ndbVersion(); 258 | void ndbWifiKeepalive(bool keepalive); 259 | void nsAutoUSBGadget(const QString &action); 260 | void nsDarkMode(const QString &action); 261 | void nsForceWifi(const QString &action); 262 | void nsInvert(const QString &action); 263 | void nsLockscreen(const QString &action); 264 | void nsScreenshots(const QString &action); 265 | void pfmRescanBooks(); 266 | void pfmRescanBooksFull(); 267 | void pwrReboot(); 268 | void pwrShutdown(); 269 | void pwrSleep(); 270 | void wfmConnectWireless(); 271 | void wfmConnectWirelessSilently(); 272 | void wfmSetAirplaneMode(const QString &action); 273 | Q_SIGNALS: // SIGNALS 274 | void dlgConfirmResult(int result); 275 | void dlgConfirmTextInput(const QString &input); 276 | void fssFinished(); 277 | void fssGotNumFilesToProcess(int num); 278 | void fssParseProgress(int progress); 279 | void ndbViewChanged(const QString &newView); 280 | void pfmAboutToConnect(); 281 | void pfmDoneProcessing(); 282 | void rvPageChanged(int pageNum); 283 | void wmLinkQualityForConnectedNetwork(double quality); 284 | void wmMacAddressAvailable(const QString &mac); 285 | void wmNetworkConnected(); 286 | void wmNetworkDisconnected(); 287 | void wmNetworkFailedToConnect(); 288 | void wmNetworkForgotten(); 289 | void wmScanningAborted(); 290 | void wmScanningFinished(); 291 | void wmScanningStarted(); 292 | void wmTryingToConnect(); 293 | void wmWifiEnabled(bool enabled); 294 | }; 295 | 296 | #endif 297 | -------------------------------------------------------------------------------- /src/interface/ndb_proxy.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file was generated by qdbusxml2cpp version 0.8 3 | * Command line was: qdbusxml2cpp -c NDBProxy -p ndb_proxy com.github.shermp.nickeldbus.xml 4 | * 5 | * qdbusxml2cpp is Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). 6 | * 7 | * This is an auto-generated file. 8 | * This file may have been hand-edited. Look for HAND-EDIT comments 9 | * before re-generating it. 10 | */ 11 | 12 | #include "ndb_proxy.h" 13 | 14 | /* 15 | * Implementation of interface class NDBProxy 16 | */ 17 | 18 | NDBProxy::NDBProxy(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent) 19 | : QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent) 20 | { 21 | } 22 | 23 | NDBProxy::~NDBProxy() 24 | { 25 | } 26 | 27 | -------------------------------------------------------------------------------- /src/interface/ndb_proxy.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file was generated by qdbusxml2cpp version 0.8 3 | * Command line was: qdbusxml2cpp -c NDBProxy -p ndb_proxy com.github.shermp.nickeldbus.xml 4 | * 5 | * qdbusxml2cpp is Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). 6 | * 7 | * This is an auto-generated file. 8 | * Do not edit! All changes made to it will be lost. 9 | */ 10 | 11 | #ifndef NDB_PROXY_H_1714266534 12 | #define NDB_PROXY_H_1714266534 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | /* 24 | * Proxy class for interface com.github.shermp.nickeldbus 25 | */ 26 | class NDBProxy: public QDBusAbstractInterface 27 | { 28 | Q_OBJECT 29 | public: 30 | static inline const char *staticInterfaceName() 31 | { return "com.github.shermp.nickeldbus"; } 32 | 33 | public: 34 | NDBProxy(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0); 35 | 36 | ~NDBProxy(); 37 | 38 | public Q_SLOTS: // METHODS 39 | inline QDBusPendingReply<> bwmOpenBrowser() 40 | { 41 | QList argumentList; 42 | return asyncCallWithArgumentList(QLatin1String("bwmOpenBrowser"), argumentList); 43 | } 44 | 45 | inline QDBusPendingReply<> bwmOpenBrowser(bool modal) 46 | { 47 | QList argumentList; 48 | argumentList << QVariant::fromValue(modal); 49 | return asyncCallWithArgumentList(QLatin1String("bwmOpenBrowser"), argumentList); 50 | } 51 | 52 | inline QDBusPendingReply<> bwmOpenBrowser(bool modal, const QString &url) 53 | { 54 | QList argumentList; 55 | argumentList << QVariant::fromValue(modal) << QVariant::fromValue(url); 56 | return asyncCallWithArgumentList(QLatin1String("bwmOpenBrowser"), argumentList); 57 | } 58 | 59 | inline QDBusPendingReply<> bwmOpenBrowser(bool modal, const QString &url, const QString &css) 60 | { 61 | QList argumentList; 62 | argumentList << QVariant::fromValue(modal) << QVariant::fromValue(url) << QVariant::fromValue(css); 63 | return asyncCallWithArgumentList(QLatin1String("bwmOpenBrowser"), argumentList); 64 | } 65 | 66 | inline QDBusPendingReply<> dlgConfirmAccept(const QString &title, const QString &body, const QString &acceptText) 67 | { 68 | QList argumentList; 69 | argumentList << QVariant::fromValue(title) << QVariant::fromValue(body) << QVariant::fromValue(acceptText); 70 | return asyncCallWithArgumentList(QLatin1String("dlgConfirmAccept"), argumentList); 71 | } 72 | 73 | inline QDBusPendingReply<> dlgConfirmAcceptReject(const QString &title, const QString &body, const QString &acceptText, const QString &rejectText) 74 | { 75 | QList argumentList; 76 | argumentList << QVariant::fromValue(title) << QVariant::fromValue(body) << QVariant::fromValue(acceptText) << QVariant::fromValue(rejectText); 77 | return asyncCallWithArgumentList(QLatin1String("dlgConfirmAcceptReject"), argumentList); 78 | } 79 | 80 | inline QDBusPendingReply<> dlgConfirmClose() 81 | { 82 | QList argumentList; 83 | return asyncCallWithArgumentList(QLatin1String("dlgConfirmClose"), argumentList); 84 | } 85 | 86 | inline QDBusPendingReply<> dlgConfirmCreate() 87 | { 88 | QList argumentList; 89 | return asyncCallWithArgumentList(QLatin1String("dlgConfirmCreate"), argumentList); 90 | } 91 | 92 | inline QDBusPendingReply<> dlgConfirmCreate(bool createLineEdit) 93 | { 94 | QList argumentList; 95 | argumentList << QVariant::fromValue(createLineEdit); 96 | return asyncCallWithArgumentList(QLatin1String("dlgConfirmCreate"), argumentList); 97 | } 98 | 99 | inline QDBusPendingReply<> dlgConfirmNoBtn(const QString &title, const QString &body) 100 | { 101 | QList argumentList; 102 | argumentList << QVariant::fromValue(title) << QVariant::fromValue(body); 103 | return asyncCallWithArgumentList(QLatin1String("dlgConfirmNoBtn"), argumentList); 104 | } 105 | 106 | inline QDBusPendingReply<> dlgConfirmReject(const QString &title, const QString &body, const QString &rejectText) 107 | { 108 | QList argumentList; 109 | argumentList << QVariant::fromValue(title) << QVariant::fromValue(body) << QVariant::fromValue(rejectText); 110 | return asyncCallWithArgumentList(QLatin1String("dlgConfirmReject"), argumentList); 111 | } 112 | 113 | inline QDBusPendingReply<> dlgConfirmSetAccept(const QString &acceptText) 114 | { 115 | QList argumentList; 116 | argumentList << QVariant::fromValue(acceptText); 117 | return asyncCallWithArgumentList(QLatin1String("dlgConfirmSetAccept"), argumentList); 118 | } 119 | 120 | inline QDBusPendingReply<> dlgConfirmSetBody(const QString &body) 121 | { 122 | QList argumentList; 123 | argumentList << QVariant::fromValue(body); 124 | return asyncCallWithArgumentList(QLatin1String("dlgConfirmSetBody"), argumentList); 125 | } 126 | 127 | inline QDBusPendingReply<> dlgConfirmSetLEPassword(bool password) 128 | { 129 | QList argumentList; 130 | argumentList << QVariant::fromValue(password); 131 | return asyncCallWithArgumentList(QLatin1String("dlgConfirmSetLEPassword"), argumentList); 132 | } 133 | 134 | inline QDBusPendingReply<> dlgConfirmSetLEPlaceholder(const QString &placeholder) 135 | { 136 | QList argumentList; 137 | argumentList << QVariant::fromValue(placeholder); 138 | return asyncCallWithArgumentList(QLatin1String("dlgConfirmSetLEPlaceholder"), argumentList); 139 | } 140 | 141 | inline QDBusPendingReply<> dlgConfirmSetModal(bool modal) 142 | { 143 | QList argumentList; 144 | argumentList << QVariant::fromValue(modal); 145 | return asyncCallWithArgumentList(QLatin1String("dlgConfirmSetModal"), argumentList); 146 | } 147 | 148 | inline QDBusPendingReply<> dlgConfirmSetProgress(int min, int max, int val) 149 | { 150 | QList argumentList; 151 | argumentList << QVariant::fromValue(min) << QVariant::fromValue(max) << QVariant::fromValue(val); 152 | return asyncCallWithArgumentList(QLatin1String("dlgConfirmSetProgress"), argumentList); 153 | } 154 | 155 | inline QDBusPendingReply<> dlgConfirmSetProgress(int min, int max, int val, const QString &format) 156 | { 157 | QList argumentList; 158 | argumentList << QVariant::fromValue(min) << QVariant::fromValue(max) << QVariant::fromValue(val) << QVariant::fromValue(format); 159 | return asyncCallWithArgumentList(QLatin1String("dlgConfirmSetProgress"), argumentList); 160 | } 161 | 162 | inline QDBusPendingReply<> dlgConfirmSetReject(const QString &rejectText) 163 | { 164 | QList argumentList; 165 | argumentList << QVariant::fromValue(rejectText); 166 | return asyncCallWithArgumentList(QLatin1String("dlgConfirmSetReject"), argumentList); 167 | } 168 | 169 | inline QDBusPendingReply<> dlgConfirmSetTitle(const QString &title) 170 | { 171 | QList argumentList; 172 | argumentList << QVariant::fromValue(title); 173 | return asyncCallWithArgumentList(QLatin1String("dlgConfirmSetTitle"), argumentList); 174 | } 175 | 176 | inline QDBusPendingReply<> dlgConfirmShow() 177 | { 178 | QList argumentList; 179 | return asyncCallWithArgumentList(QLatin1String("dlgConfirmShow"), argumentList); 180 | } 181 | 182 | inline QDBusPendingReply<> dlgConfirmShowClose(bool show) 183 | { 184 | QList argumentList; 185 | argumentList << QVariant::fromValue(show); 186 | return asyncCallWithArgumentList(QLatin1String("dlgConfirmShowClose"), argumentList); 187 | } 188 | 189 | inline QDBusPendingReply imgSizeForType(const QString &type) 190 | { 191 | QList argumentList; 192 | argumentList << QVariant::fromValue(type); 193 | return asyncCallWithArgumentList(QLatin1String("imgSizeForType"), argumentList); 194 | } 195 | 196 | inline QDBusPendingReply<> mwcHome() 197 | { 198 | QList argumentList; 199 | return asyncCallWithArgumentList(QLatin1String("mwcHome"), argumentList); 200 | } 201 | 202 | inline QDBusPendingReply<> mwcToast(int toastDuration, const QString &msgMain) 203 | { 204 | QList argumentList; 205 | argumentList << QVariant::fromValue(toastDuration) << QVariant::fromValue(msgMain); 206 | return asyncCallWithArgumentList(QLatin1String("mwcToast"), argumentList); 207 | } 208 | 209 | inline QDBusPendingReply<> mwcToast(int toastDuration, const QString &msgMain, const QString &msgSub) 210 | { 211 | QList argumentList; 212 | argumentList << QVariant::fromValue(toastDuration) << QVariant::fromValue(msgMain) << QVariant::fromValue(msgSub); 213 | return asyncCallWithArgumentList(QLatin1String("mwcToast"), argumentList); 214 | } 215 | 216 | inline QDBusPendingReply<> n3fssSyncBoth() 217 | { 218 | QList argumentList; 219 | return asyncCallWithArgumentList(QLatin1String("n3fssSyncBoth"), argumentList); 220 | } 221 | 222 | inline QDBusPendingReply<> n3fssSyncOnboard() 223 | { 224 | QList argumentList; 225 | return asyncCallWithArgumentList(QLatin1String("n3fssSyncOnboard"), argumentList); 226 | } 227 | 228 | inline QDBusPendingReply<> n3fssSyncSD() 229 | { 230 | QList argumentList; 231 | return asyncCallWithArgumentList(QLatin1String("n3fssSyncSD"), argumentList); 232 | } 233 | 234 | inline QDBusPendingReply ndbCurrentView() 235 | { 236 | QList argumentList; 237 | return asyncCallWithArgumentList(QLatin1String("ndbCurrentView"), argumentList); 238 | } 239 | 240 | inline QDBusPendingReply ndbFirmwareVersion() 241 | { 242 | QList argumentList; 243 | return asyncCallWithArgumentList(QLatin1String("ndbFirmwareVersion"), argumentList); 244 | } 245 | 246 | inline QDBusPendingReply ndbNickelClassDetails(const QString &staticMmetaobjectSymbol) 247 | { 248 | QList argumentList; 249 | argumentList << QVariant::fromValue(staticMmetaobjectSymbol); 250 | return asyncCallWithArgumentList(QLatin1String("ndbNickelClassDetails"), argumentList); 251 | } 252 | 253 | inline QDBusPendingReply ndbNickelWidgets() 254 | { 255 | QList argumentList; 256 | return asyncCallWithArgumentList(QLatin1String("ndbNickelWidgets"), argumentList); 257 | } 258 | 259 | inline QDBusPendingReply ndbSignalConnected(const QString &signalName) 260 | { 261 | QList argumentList; 262 | argumentList << QVariant::fromValue(signalName); 263 | return asyncCallWithArgumentList(QLatin1String("ndbSignalConnected"), argumentList); 264 | } 265 | 266 | inline QDBusPendingReply ndbVersion() 267 | { 268 | QList argumentList; 269 | return asyncCallWithArgumentList(QLatin1String("ndbVersion"), argumentList); 270 | } 271 | 272 | inline QDBusPendingReply<> ndbWifiKeepalive(bool keepalive) 273 | { 274 | QList argumentList; 275 | argumentList << QVariant::fromValue(keepalive); 276 | return asyncCallWithArgumentList(QLatin1String("ndbWifiKeepalive"), argumentList); 277 | } 278 | 279 | inline QDBusPendingReply<> nsAutoUSBGadget(const QString &action) 280 | { 281 | QList argumentList; 282 | argumentList << QVariant::fromValue(action); 283 | return asyncCallWithArgumentList(QLatin1String("nsAutoUSBGadget"), argumentList); 284 | } 285 | 286 | inline QDBusPendingReply<> nsDarkMode(const QString &action) 287 | { 288 | QList argumentList; 289 | argumentList << QVariant::fromValue(action); 290 | return asyncCallWithArgumentList(QLatin1String("nsDarkMode"), argumentList); 291 | } 292 | 293 | inline QDBusPendingReply<> nsForceWifi(const QString &action) 294 | { 295 | QList argumentList; 296 | argumentList << QVariant::fromValue(action); 297 | return asyncCallWithArgumentList(QLatin1String("nsForceWifi"), argumentList); 298 | } 299 | 300 | inline QDBusPendingReply<> nsInvert(const QString &action) 301 | { 302 | QList argumentList; 303 | argumentList << QVariant::fromValue(action); 304 | return asyncCallWithArgumentList(QLatin1String("nsInvert"), argumentList); 305 | } 306 | 307 | inline QDBusPendingReply<> nsLockscreen(const QString &action) 308 | { 309 | QList argumentList; 310 | argumentList << QVariant::fromValue(action); 311 | return asyncCallWithArgumentList(QLatin1String("nsLockscreen"), argumentList); 312 | } 313 | 314 | inline QDBusPendingReply<> nsScreenshots(const QString &action) 315 | { 316 | QList argumentList; 317 | argumentList << QVariant::fromValue(action); 318 | return asyncCallWithArgumentList(QLatin1String("nsScreenshots"), argumentList); 319 | } 320 | 321 | inline QDBusPendingReply<> pfmRescanBooks() 322 | { 323 | QList argumentList; 324 | return asyncCallWithArgumentList(QLatin1String("pfmRescanBooks"), argumentList); 325 | } 326 | 327 | inline QDBusPendingReply<> pfmRescanBooksFull() 328 | { 329 | QList argumentList; 330 | return asyncCallWithArgumentList(QLatin1String("pfmRescanBooksFull"), argumentList); 331 | } 332 | 333 | inline QDBusPendingReply<> pwrReboot() 334 | { 335 | QList argumentList; 336 | return asyncCallWithArgumentList(QLatin1String("pwrReboot"), argumentList); 337 | } 338 | 339 | inline QDBusPendingReply<> pwrShutdown() 340 | { 341 | QList argumentList; 342 | return asyncCallWithArgumentList(QLatin1String("pwrShutdown"), argumentList); 343 | } 344 | 345 | inline QDBusPendingReply<> pwrSleep() 346 | { 347 | QList argumentList; 348 | return asyncCallWithArgumentList(QLatin1String("pwrSleep"), argumentList); 349 | } 350 | 351 | inline QDBusPendingReply<> wfmConnectWireless() 352 | { 353 | QList argumentList; 354 | return asyncCallWithArgumentList(QLatin1String("wfmConnectWireless"), argumentList); 355 | } 356 | 357 | inline QDBusPendingReply<> wfmConnectWirelessSilently() 358 | { 359 | QList argumentList; 360 | return asyncCallWithArgumentList(QLatin1String("wfmConnectWirelessSilently"), argumentList); 361 | } 362 | 363 | inline QDBusPendingReply<> wfmSetAirplaneMode(const QString &action) 364 | { 365 | QList argumentList; 366 | argumentList << QVariant::fromValue(action); 367 | return asyncCallWithArgumentList(QLatin1String("wfmSetAirplaneMode"), argumentList); 368 | } 369 | 370 | Q_SIGNALS: // SIGNALS 371 | void dlgConfirmResult(int result); 372 | void dlgConfirmTextInput(const QString &input); 373 | void fssFinished(); 374 | void fssGotNumFilesToProcess(int num); 375 | void fssParseProgress(int progress); 376 | void ndbViewChanged(const QString &newView); 377 | void pfmAboutToConnect(); 378 | void pfmDoneProcessing(); 379 | void rvPageChanged(int pageNum); 380 | void wmLinkQualityForConnectedNetwork(double quality); 381 | void wmMacAddressAvailable(const QString &mac); 382 | void wmNetworkConnected(); 383 | void wmNetworkDisconnected(); 384 | void wmNetworkFailedToConnect(); 385 | void wmNetworkForgotten(); 386 | void wmScanningAborted(); 387 | void wmScanningFinished(); 388 | void wmScanningStarted(); 389 | void wmTryingToConnect(); 390 | void wmWifiEnabled(bool enabled); 391 | }; 392 | 393 | namespace com { 394 | namespace github { 395 | namespace shermp { 396 | typedef ::NDBProxy nickeldbus; 397 | } 398 | } 399 | } 400 | #endif 401 | -------------------------------------------------------------------------------- /src/ndb/NDBCfmDlg.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "util.h" 5 | #include "NDBCfmDlg.h" 6 | 7 | #define DLG_ASSERT(ret, cond, str) if (!(cond)) { \ 8 | errString = QString("%1: %2").arg(__func__).arg(str); \ 9 | return (ret); \ 10 | } 11 | 12 | #define DLG_ASSERT_CLOSE(ret, cond, str) if (!(cond)) { \ 13 | errString = QString("%1: %2").arg(__func__).arg(str); \ 14 | if (dlg) { \ 15 | connectStdSignals(); \ 16 | closeDialog(); \ 17 | } \ 18 | return (ret); \ 19 | } 20 | 21 | namespace NDB { 22 | 23 | NDBCfmDlg::NDBCfmDlg(QObject* parent) : QObject(parent) { 24 | initResult = Ok; 25 | currActiveType = TypeStd; 26 | dlgStyleSheet = QString(R"( 27 | * { 28 | font-family: Avenir, sans-serif; 29 | font-style: normal; 30 | padding: 0px; 31 | margin: 0px; 32 | } 33 | *[localeName="ja"] { 34 | font-family: Sans-SerifJP, sans-serif; 35 | font-style: normal; 36 | } 37 | *[localeName="zh"] { 38 | font-family: Sans-SerifZH-Simplified, sans-serif; 39 | font-style: normal; 40 | } 41 | *[localeName="zh-HK"] { 42 | font-family: Sans-SerifZH-Traditional, sans-serif; 43 | font-style: normal; 44 | } 45 | *[localeName="zh-TW"] { 46 | font-family: Sans-SerifZH-Traditional, sans-serif; 47 | font-style: normal; 48 | } 49 | 50 | *[qApp_deviceIsTrilogy=true] { 51 | font-size: 23px; 52 | } 53 | *[qApp_deviceIsPhoenix=true] { 54 | font-size: 26px; 55 | } 56 | *[qApp_deviceIsDragon=true] { 57 | font-size: 32px; 58 | } 59 | *[qApp_deviceIsAlyssum=true] { 60 | font-size: 35px; 61 | } 62 | *[qApp_deviceIsNova=true] { 63 | font-size: 35px; 64 | } 65 | *[qApp_deviceIsStorm=true] { 66 | font-size: 44px; 67 | } 68 | *[qApp_deviceIsDaylight=true] { 69 | font-size: 42px; 70 | } 71 | )"); 72 | 73 | /* Resolve symbols */ 74 | // Confirmation Dialog 75 | resolveSymbolRTLD("_ZN25ConfirmationDialogFactory21getConfirmationDialogEP7QWidget", nh_symoutptr(symbols.ConfirmationDialogFactory_getConfirmationDialog)); 76 | resolveSymbolRTLD("_ZN25ConfirmationDialogFactory18showTextEditDialogERK7QString", nh_symoutptr(symbols.ConfirmationDialogFactory_showTextEditDialog)); 77 | resolveSymbolRTLD("_ZN18ConfirmationDialog8setTitleERK7QString", nh_symoutptr(symbols.ConfirmationDialog__setTitle)); 78 | resolveSymbolRTLD("_ZN18ConfirmationDialog7setTextERK7QString", nh_symoutptr(symbols.ConfirmationDialog__setText)); 79 | resolveSymbolRTLD("_ZN18ConfirmationDialog19setAcceptButtonTextERK7QString", nh_symoutptr(symbols.ConfirmationDialog__setAcceptButtonText)); 80 | resolveSymbolRTLD("_ZN18ConfirmationDialog19setRejectButtonTextERK7QString", nh_symoutptr(symbols.ConfirmationDialog__setRejectButtonText)); 81 | resolveSymbolRTLD("_ZN18ConfirmationDialog15showCloseButtonEb", nh_symoutptr(symbols.ConfirmationDialog__showCloseButton)); 82 | resolveSymbolRTLD("_ZN18ConfirmationDialog21setRejectOnOutsideTapEb", nh_symoutptr(symbols.ConfirmationDialog__setRejectOnOutsideTap)); 83 | resolveSymbolRTLD("_ZN18ConfirmationDialog9addWidgetEP7QWidget", nh_symoutptr(symbols.ConfirmationDialog__addWidget)); 84 | 85 | // Keyboard stuff 86 | resolveSymbolRTLD("_ZN27N3ConfirmationTextEditFieldC1EP18ConfirmationDialog14KeyboardScript", nh_symoutptr(symbols.N3ConfirmationTextEditField__N3ConfirmationTextEditFieldKS)); 87 | if (!symbols.N3ConfirmationTextEditField__N3ConfirmationTextEditFieldKS) { 88 | // FW 4.6 has a slightly different constructor without the KeyboardScript stuff 89 | resolveSymbolRTLD("_ZN27N3ConfirmationTextEditFieldC1EP18ConfirmationDialog", nh_symoutptr(symbols.N3ConfirmationTextEditField__N3ConfirmationTextEditField)); 90 | } 91 | resolveSymbolRTLD("_ZNK27N3ConfirmationTextEditField8textEditEv", nh_symoutptr(symbols.N3ConfirmationTextEditField__textEdit)); 92 | } 93 | 94 | NDBCfmDlg::~NDBCfmDlg() { 95 | } 96 | 97 | void NDBCfmDlg::connectStdSignals() { 98 | if (dlg) { 99 | NDB_DEBUG("connecting standard signals"); 100 | // Connecting accept/reject signals instead of finished, because for some 101 | // reason the dialog created by 'showTextEditDialog()' connects the accept 102 | // button tap directly to the 'accepted' signal, instead of the 'accept' slot. 103 | // If Kobo ever changes this behaviour, the following code should still work. 104 | QObject::connect(dlg, &QDialog::accepted, dlg, &QDialog::deleteLater, Qt::UniqueConnection); 105 | QObject::connect(dlg, &QDialog::rejected, dlg, &QDialog::deleteLater, Qt::UniqueConnection); 106 | } 107 | } 108 | 109 | N3ConfirmationTextEditField* NDBCfmDlg::createTextEditField() { 110 | N3ConfirmationTextEditField *t = reinterpret_cast(calloc(1,128)); 111 | if (!t || !dlg) {return nullptr;} 112 | if (symbols.N3ConfirmationTextEditField__N3ConfirmationTextEditFieldKS) { 113 | symbols.N3ConfirmationTextEditField__N3ConfirmationTextEditFieldKS(t, dlg, 1); 114 | } else { 115 | symbols.N3ConfirmationTextEditField__N3ConfirmationTextEditField(t, dlg); 116 | } 117 | return t; 118 | } 119 | 120 | enum Result NDBCfmDlg::createDialog(enum dialogType dlgType) { 121 | DLG_ASSERT(ForbiddenError, !dlg, "dialog already open"); 122 | DLG_ASSERT_CLOSE( 123 | SymbolError, 124 | symbols.ConfirmationDialogFactory_getConfirmationDialog && 125 | symbols.ConfirmationDialogFactory_showTextEditDialog && 126 | symbols.ConfirmationDialog__setTitle && 127 | symbols.ConfirmationDialog__setText && 128 | symbols.ConfirmationDialog__setAcceptButtonText && 129 | symbols.ConfirmationDialog__setRejectButtonText && 130 | symbols.ConfirmationDialog__setRejectOnOutsideTap && 131 | symbols.ConfirmationDialog__showCloseButton, 132 | "could not find one or more standard dialog symbols" 133 | ); 134 | if (dlgType == TypeLineEdit) { 135 | DLG_ASSERT_CLOSE( 136 | SymbolError, 137 | (symbols.N3ConfirmationTextEditField__N3ConfirmationTextEditFieldKS || 138 | symbols.N3ConfirmationTextEditField__N3ConfirmationTextEditField) && 139 | symbols.N3ConfirmationTextEditField__textEdit, 140 | "could not find text edit symbols" 141 | ); 142 | } 143 | 144 | switch (dlgType) { 145 | case TypeStd: 146 | dlg = symbols.ConfirmationDialogFactory_getConfirmationDialog(nullptr); 147 | DLG_ASSERT_CLOSE(NullError, dlg, "could not get confirmation dialog"); 148 | currActiveType = TypeStd; 149 | break; 150 | 151 | case TypeLineEdit: 152 | dlg = symbols.ConfirmationDialogFactory_showTextEditDialog(""); 153 | DLG_ASSERT_CLOSE(NullError, dlg, "could not get line edit dialog"); 154 | dlg->hide(); 155 | tef = createTextEditField(); 156 | DLG_ASSERT_CLOSE(NullError, tef, "error getting text edit field"); 157 | tle = symbols.N3ConfirmationTextEditField__textEdit(tef); 158 | DLG_ASSERT_CLOSE(NullError, tle, "error getting TouchLineEdit"); 159 | // Make the 'Go' key accept the dialog. 160 | if (!QObject::connect(tef, SIGNAL(commitRequested()), dlg, SIGNAL(accepted()))) { 161 | nh_log("unable to connect N3ConfirmationTextEditField::commitRequested() to ConfirmationDialog::accepted()"); 162 | } 163 | currActiveType = TypeLineEdit; 164 | break; 165 | 166 | default: 167 | DLG_ASSERT(ParamError, false, "Incorrect dialog type passed"); 168 | break; 169 | } 170 | 171 | dlg->setModal(true); 172 | return Ok; 173 | } 174 | 175 | enum Result NDBCfmDlg::showDialog() { 176 | DLG_ASSERT(ForbiddenError, dlg, "dialog not open"); 177 | connectStdSignals(); 178 | dlg->open(); 179 | return Ok; 180 | } 181 | 182 | enum Result NDBCfmDlg::closeDialog() { 183 | DLG_ASSERT(ForbiddenError, dlg, "dialog not open"); 184 | dlg->accept(); 185 | return Ok; 186 | } 187 | 188 | enum Result NDBCfmDlg::setTitle(QString const& title) { 189 | DLG_ASSERT(ForbiddenError, dlg, "dialog not open"); 190 | symbols.ConfirmationDialog__setTitle(dlg, title); 191 | return Ok; 192 | } 193 | 194 | enum Result NDBCfmDlg::setBody(QString const& body) { 195 | DLG_ASSERT(ForbiddenError, dlg, "dialog not open"); 196 | DLG_ASSERT(ForbiddenError, currActiveType == TypeStd, "not standard dialog"); 197 | symbols.ConfirmationDialog__setText(dlg, body); 198 | return Ok; 199 | } 200 | 201 | enum Result NDBCfmDlg::setAccept(QString const& acceptText) { 202 | DLG_ASSERT(ForbiddenError, dlg, "dialog not open"); 203 | symbols.ConfirmationDialog__setAcceptButtonText(dlg, acceptText); 204 | return Ok; 205 | } 206 | 207 | enum Result NDBCfmDlg::setReject(QString const& rejectText) { 208 | DLG_ASSERT(ForbiddenError, dlg, "dialog not open"); 209 | symbols.ConfirmationDialog__setRejectButtonText(dlg, rejectText); 210 | return Ok; 211 | } 212 | 213 | enum Result NDBCfmDlg::setModal(bool modal) { 214 | DLG_ASSERT(ForbiddenError, dlg, "dialog not open"); 215 | symbols.ConfirmationDialog__setRejectOnOutsideTap(dlg, !modal); 216 | return Ok; 217 | } 218 | 219 | enum Result NDBCfmDlg::showClose(bool show) { 220 | DLG_ASSERT(ForbiddenError, dlg, "dialog not open"); 221 | symbols.ConfirmationDialog__showCloseButton(dlg, show); 222 | return Ok; 223 | } 224 | 225 | enum Result NDBCfmDlg::setProgress(int min, int max, int val, QString const& format) { 226 | DLG_ASSERT(ForbiddenError, dlg, "dialog not open"); 227 | DLG_ASSERT(ForbiddenError, currActiveType == TypeStd, "not standard dialog"); 228 | DLG_ASSERT(SymbolError, symbols.ConfirmationDialog__addWidget, "could not find addWidget symbol"); 229 | bool added = true; 230 | if (min < 0 || max < 0 || val < 0) { 231 | if (prog) { 232 | prog->hide(); 233 | } 234 | return Ok; 235 | } else if (prog) { 236 | prog->show(); 237 | } 238 | if (!prog) { 239 | prog = new NDBProgressBar(); 240 | prog->setStyleSheet(dlgStyleSheet); 241 | added = false; 242 | } 243 | prog->setMinimum(min); 244 | prog->setMaximum(max); 245 | prog->setValue(val); 246 | if (!format.isEmpty()) { 247 | prog->setFormat(format); 248 | } 249 | if (!added) { 250 | symbols.ConfirmationDialog__addWidget(dlg, prog); 251 | } 252 | return Ok; 253 | } 254 | 255 | enum Result NDBCfmDlg::setLEPassword(bool isPassword) { 256 | DLG_ASSERT(ForbiddenError, dlg, "dialog not open"); 257 | DLG_ASSERT(ForbiddenError, currActiveType == TypeLineEdit, "not LineEdit dialog"); 258 | DLG_ASSERT(NullError, tef, "TextEditField is null"); 259 | 260 | TouchCheckBox* tcb = tef->findChild(QString("showPassword")); 261 | if (tcb) { 262 | if (isPassword) { 263 | tcb->setChecked(false); 264 | tcb->show(); 265 | } 266 | else { 267 | tcb->setChecked(true); 268 | tcb->hide(); 269 | } 270 | } 271 | return Ok; 272 | } 273 | enum Result NDBCfmDlg::setLEPlaceholder(QString const& placeholder) { 274 | DLG_ASSERT(ForbiddenError, dlg, "dialog not open"); 275 | DLG_ASSERT(ForbiddenError, currActiveType == TypeLineEdit, "not LineEdit dialog"); 276 | DLG_ASSERT(NullError, tle, "TouchLineEdit is null"); 277 | tle->setPlaceholderText(placeholder); 278 | return Ok; 279 | } 280 | 281 | QString NDBCfmDlg::getLEText() { 282 | QString res; 283 | DLG_ASSERT(res, dlg, "dialog not open"); 284 | DLG_ASSERT(res, currActiveType == TypeLineEdit, "not LineEdit dialog"); 285 | DLG_ASSERT(res, tle, "TouchLineEdit is null"); 286 | return tle->text(); 287 | } 288 | 289 | } // namespace NDB 290 | 291 | /* 292 | * A note on my current understanding of how the keyboard stuff works: 293 | * 294 | * Start with a TouchLineEdit (TLE) or TouchTextEdit (TTE). TouchLineEdit is a subclass 295 | * of QLineEdit, TouchLineEdit is a subclass of a QFrame, which contains a 296 | * QTextEdit. 297 | * 298 | * To attach the keyboard to the above widgets, a KeyboardReceiver (KR) is used, the 299 | * constructor for this adds a KR as a child object of the TLE or 300 | * TTE. 301 | * 302 | * Both the edit widgets and KR need to be manually heap allocated before use. Care 303 | * needs to be taken that enough memory is allocated. 304 | * 305 | * The keyboard itself is contained in a KeyboardFrame (KF). The ConfirmationDialog 306 | * already contains a KF, and has a method to get a pointer to it (ConfirmationDialog::keyboardFrame()). 307 | * The KF has a method to create the actual keyboard (KeyboardFrame::createKeyboard()), 308 | * which is locale dependent. One of the parameters required for createKeyboard() is a 309 | * KeyboardScript, which is unknown at this time, but is likely an enum. 310 | * 311 | * createKeyboard() returns (a pointer to) a SearchKeyboardController (SKC), whic is a 312 | * descendant of the KeyboardController (KC) class. To finally connect the edit widget 313 | * to the keyboard, SearchKeyboardController::setReceiver() is used to set the previously 314 | * created KR to the SKC. 315 | * 316 | * To actually show and hide the keyboard, we can use QWidget::show() and QWidget::hide() on the 317 | * KF. The edit widgets have a tapped() signal used to show the keyboard, and the KC has a 318 | * commitRequested() signal to hide the keyboard when the 'go' key is pressed. 319 | */ 320 | -------------------------------------------------------------------------------- /src/ndb/NDBCfmDlg.h: -------------------------------------------------------------------------------- 1 | #ifndef NDB_CONFIRM_DLG_H 2 | #define NDB_CONFIRM_DLG_H 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include "NDBWidgets.h" 11 | #include "ndb.h" 12 | 13 | typedef QDialog ConfirmationDialog; 14 | typedef int KeyboardScript; 15 | typedef QLineEdit TouchLineEdit; 16 | typedef QWidget N3ConfirmationTextEditField; 17 | typedef QCheckBox TouchCheckBox; 18 | 19 | namespace NDB { 20 | 21 | class NDBCfmDlg : public QObject { 22 | Q_OBJECT 23 | public: 24 | enum dialogType {TypeStd, TypeLineEdit}; 25 | enum Result initResult; 26 | NDBCfmDlg(QObject* parent); 27 | ~NDBCfmDlg(); 28 | QString errString; 29 | QPointer dlg; 30 | enum Result createDialog(enum dialogType dlgType); 31 | enum Result setTitle(const QString& title); 32 | enum Result setBody(QString const& body); 33 | enum Result setAccept(QString const& acceptText); 34 | enum Result setReject(QString const& rejectText); 35 | enum Result setModal(bool modal); 36 | enum Result showClose(bool show); 37 | enum Result setProgress(int min, int max, int val, QString const& format = ""); 38 | enum Result setLEPassword(bool isPassword); 39 | enum Result setLEPlaceholder(QString const& placeholder); 40 | QString getLEText(); 41 | enum Result showDialog(); 42 | enum Result closeDialog(); 43 | 44 | private: 45 | struct { 46 | ConfirmationDialog *(*ConfirmationDialogFactory_getConfirmationDialog)(QWidget*); 47 | ConfirmationDialog *(*ConfirmationDialogFactory_showTextEditDialog)(QString const& title); 48 | void (*ConfirmationDialog__setTitle)(ConfirmationDialog* _this, QString const&); 49 | void (*ConfirmationDialog__setText)(ConfirmationDialog* _this, QString const&); 50 | void (*ConfirmationDialog__setAcceptButtonText)(ConfirmationDialog* _this, QString const&); 51 | void (*ConfirmationDialog__setRejectButtonText)(ConfirmationDialog* _this, QString const&); 52 | void (*ConfirmationDialog__showCloseButton)(ConfirmationDialog* _this, bool show); 53 | void (*ConfirmationDialog__setRejectOnOutsideTap)(ConfirmationDialog* _this, bool setReject); 54 | void (*ConfirmationDialog__addWidget)(ConfirmationDialog* _this, QWidget* w); 55 | N3ConfirmationTextEditField *(*N3ConfirmationTextEditField__N3ConfirmationTextEditFieldKS)( 56 | N3ConfirmationTextEditField* _this, 57 | ConfirmationDialog* dlg, 58 | KeyboardScript ks); 59 | N3ConfirmationTextEditField *(*N3ConfirmationTextEditField__N3ConfirmationTextEditField)( 60 | N3ConfirmationTextEditField* _this, 61 | ConfirmationDialog* dlg 62 | ); 63 | TouchLineEdit *(*N3ConfirmationTextEditField__textEdit)(N3ConfirmationTextEditField* _this); 64 | } symbols; 65 | enum dialogType currActiveType; 66 | QString dlgStyleSheet; 67 | QPointer prog; 68 | QPointer tle; 69 | QPointer tef; 70 | N3ConfirmationTextEditField* createTextEditField(); 71 | void connectStdSignals(); 72 | 73 | }; 74 | 75 | } // namespace NDB 76 | 77 | #endif // NDB_CONFIRM_DLG_H 78 | -------------------------------------------------------------------------------- /src/ndb/NDBDbus.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include "../../NickelMenu/src/action.h" 11 | #include "../../NickelMenu/src/util.h" 12 | #include "util.h" 13 | #include "NDBDbus.h" 14 | #include "../interface/ndb_adapter.h" 15 | 16 | /*! 17 | * \namespace NDB 18 | * 19 | * \brief Contains classes and methods for NickelDBus 20 | */ 21 | namespace NDB { 22 | /*! 23 | * \class NDB::NDBDbus 24 | * \inmodule NickelDBus 25 | * \brief The NDBDbus class registers a service on d-bus of Kobo e-readers. 26 | * 27 | * NDBDbus provides a bridge between Kobo's proprietary software, libnickel, 28 | * and other software running on Kobo e-readers. It registers itself as a 29 | * service on d-bus, and provides methods and signals to monitor and interact 30 | * with nickel. 31 | * 32 | */ 33 | 34 | /*! 35 | * \internal 36 | * \brief Construct a new Nickel D-Bus object 37 | * 38 | * \a parent QObject 39 | */ 40 | NDBDbus::NDBDbus(QObject* parent) : QObject(parent), QDBusContext() { 41 | new NDBAdapter(this); 42 | initSucceeded = true; 43 | nh_log("NickelDBus: registering object %s", NDB_DBUS_OBJECT_PATH); 44 | if (!conn.registerObject(NDB_DBUS_OBJECT_PATH, this)) { 45 | nh_log("NickelDBus: failed to register object on system bus"); 46 | initSucceeded = false; 47 | return; 48 | } 49 | nh_log("NickelDBus: registering interface %s", NDB_DBUS_IFACE_NAME); 50 | if (!conn.registerService(NDB_DBUS_IFACE_NAME)) { 51 | nh_log("NickelDBus: failed to register service on the system bus"); 52 | initSucceeded = false; 53 | return; 54 | } 55 | libnickel = dlopen("libnickel.so.1.0.0", RTLD_LAZY|RTLD_NODELETE); 56 | if (!libnickel) { 57 | nh_log("NickelDBus: could not dlopen libnickel"); 58 | initSucceeded = false; 59 | return; 60 | } 61 | // The following symbols are required. If they can't be resolved, bail out 62 | NDB_RESOLVE_SYMBOL("_ZN11PlugManager14sharedInstanceEv", nh_symoutptr(nSym.PlugManager__sharedInstance)); 63 | NDB_RESOLVE_SYMBOL("_ZNK11PlugManager10gadgetModeEv", nh_symoutptr(nSym.PlugManager__gadgetMode)); 64 | if (!nSym.PlugManager__gadgetMode) { 65 | // Older firmware versions use a slightly different mangled symbol 66 | NDB_RESOLVE_SYMBOL("_ZN11PlugManager10gadgetModeEv", nh_symoutptr(nSym.PlugManager__gadgetMode)); 67 | } 68 | if (!nSym.PlugManager__sharedInstance || !nSym.PlugManager__gadgetMode) { 69 | initSucceeded = false; 70 | return; 71 | } 72 | // Setup view change timer 73 | viewTimer = new QTimer(this); 74 | if (!viewTimer) { 75 | nh_log("failed to create viewTimer"); 76 | initSucceeded = false; 77 | return; 78 | } 79 | // Setup the Confirmation Dialog object 80 | cfmDlg = new NDBCfmDlg(this); 81 | if (!cfmDlg || cfmDlg->initResult == InitError) { 82 | nh_log("failed to create confirmation dialog object"); 83 | initSucceeded = false; 84 | return; 85 | } 86 | // // Setup the N3 Dialog object 87 | // n3Dlg = new NDBN3Dlg(this); 88 | // if (!n3Dlg || n3Dlg->initResult == NDBN3Dlg::InitError) { 89 | // nh_log("failed to create N3 Dialog object"); 90 | // initSucceeded = false; 91 | // return; 92 | // } 93 | viewTimer->setSingleShot(true); 94 | QObject::connect(viewTimer, &QTimer::timeout, this, &NDBDbus::handleQSWTimer); 95 | 96 | // Resolve the rest of the Nickel symbols up-front 97 | // PlugWorkFlowManager 98 | NDB_RESOLVE_SYMBOL("_ZN19PlugWorkflowManager14sharedInstanceEv", nh_symoutptr(nSym.PlugWorkflowManager_sharedInstance)); 99 | // N3FSSyncManager 100 | NDB_RESOLVE_SYMBOL("_ZN15N3FSSyncManager14sharedInstanceEv", nh_symoutptr(nSym.N3FSSyncManager__sharedInstance)); 101 | NDB_RESOLVE_SYMBOL("_ZN15N3FSSyncManager4syncERK11QStringList", nh_symoutptr(nSym.N3FSSyncManager__sync)); 102 | // WirelessManager 103 | NDB_RESOLVE_SYMBOL("_ZN15WirelessManager14sharedInstanceEv", nh_symoutptr(nSym.WirelesManager_sharedInstance)); 104 | // Toast 105 | NDB_RESOLVE_SYMBOL("_ZN20MainWindowController14sharedInstanceEv", nh_symoutptr(nSym.MainWindowController_sharedInstance)); 106 | NDB_RESOLVE_SYMBOL("_ZN20MainWindowController5toastERK7QStringS2_i", nh_symoutptr(nSym.MainWindowController_toast)); 107 | // Get N3Dialog content 108 | NDB_RESOLVE_SYMBOL("_ZN8N3Dialog7contentEv", nh_symoutptr(nSym.N3Dialog__content)); 109 | // Device (for FW version) 110 | NDB_RESOLVE_SYMBOL("_ZN6Device16getCurrentDeviceEv", nh_symoutptr(nSym.Device__getCurrentDevice)); 111 | NDB_RESOLVE_SYMBOL("_ZNK6Device9userAgentEv", nh_symoutptr(nSym.Device__userAgent)); 112 | // MWC views 113 | NDB_RESOLVE_SYMBOL("_ZNK20MainWindowController11currentViewEv", nh_symoutptr(nSym.MainWindowController_currentView)); 114 | if (!nSym.MainWindowController_currentView) { 115 | // Older firmware versions use a slightly different mangled symbol name 116 | NDB_RESOLVE_SYMBOL("_ZN20MainWindowController11currentViewEv", nh_symoutptr(nSym.MainWindowController_currentView)); 117 | } 118 | // Image 119 | NDB_RESOLVE_SYMBOL("_ZN5Image11sizeForTypeERK6DeviceRK7QString", nh_symoutptr(nSym.Image__sizeForType)); 120 | NDB_RESOLVE_SYMBOL("_ZN16WirelessWatchdog14sharedInstanceEv", nh_symoutptr(nSym.WirelessWatchdog__sharedInstance)); 121 | } 122 | 123 | /*! 124 | * \internal 125 | * \brief Destroy the NDBDbus::NDBDbus object 126 | */ 127 | NDBDbus::~NDBDbus() { 128 | delete viewTimer; 129 | conn.unregisterService(NDB_DBUS_IFACE_NAME); 130 | conn.unregisterObject(NDB_DBUS_OBJECT_PATH); 131 | } 132 | 133 | template 134 | void NDBDbus::ndbConnectSignal(T *srcObj, const char *srcSignal, const char *dest) { 135 | const char *dest_start = dest + 1; 136 | const char *dest_end = strchr(dest_start, '('); 137 | nh_log("connecting %s to %s", srcSignal, dest); 138 | if (QObject::connect(srcObj, srcSignal, this, dest)) { 139 | connectedSignals.insert(QString::fromLatin1(dest_start, dest_end - dest_start)); 140 | } else { 141 | nh_log("failed to connect %s to %s", srcSignal, dest); 142 | } 143 | } 144 | 145 | /*! 146 | * \internal 147 | * \brief Connects available Nickel signals to d-bus 148 | * 149 | * Failures to connect a signal will stop execution, the failure will be logged 150 | * to syslog. 151 | */ 152 | void NDBDbus::connectSignals() { 153 | if (nSym.PlugWorkflowManager_sharedInstance) { 154 | PlugWorkflowManager *wf = nSym.PlugWorkflowManager_sharedInstance(); 155 | if (wf) { 156 | ndbConnectSignal(wf, SIGNAL(aboutToConnect()), SIGNAL(pfmAboutToConnect())); 157 | ndbConnectSignal(wf, SIGNAL(doneProcessing()), SIGNAL(pfmDoneProcessing())); 158 | } else { 159 | nh_log("could not get shared PlugWorkflowManager pointer"); 160 | } 161 | } 162 | if (nSym.WirelesManager_sharedInstance) { 163 | WirelessManager *wm = nSym.WirelesManager_sharedInstance(); 164 | if (wm) { 165 | ndbConnectSignal(wm, SIGNAL(tryingToConnect()), SIGNAL(wmTryingToConnect())); 166 | ndbConnectSignal(wm, SIGNAL(networkConnected()), SIGNAL(wmNetworkConnected())); 167 | ndbConnectSignal(wm, SIGNAL(networkDisconnected()), SIGNAL(wmNetworkDisconnected())); 168 | ndbConnectSignal(wm, SIGNAL(networkForgotten()), SIGNAL(wmNetworkForgotten())); 169 | ndbConnectSignal(wm, SIGNAL(networkFailedToConnect()), SIGNAL(wmNetworkFailedToConnect())); 170 | ndbConnectSignal(wm, SIGNAL(scanningStarted()), SIGNAL(wmScanningStarted())); 171 | ndbConnectSignal(wm, SIGNAL(scanningFinished()), SIGNAL(wmScanningFinished())); 172 | ndbConnectSignal(wm, SIGNAL(scanningAborted()), SIGNAL(wmScanningAborted())); 173 | ndbConnectSignal(wm, SIGNAL(wifiEnabled(bool)), SIGNAL(wmWifiEnabled(bool))); 174 | ndbConnectSignal(wm, SIGNAL(linkQualityForConnectedNetwork(double)), SIGNAL(wmLinkQualityForConnectedNetwork(double))); 175 | ndbConnectSignal(wm, SIGNAL(macAddressAvailable(QString)), SIGNAL(wmMacAddressAvailable(QString))); 176 | } else { 177 | nh_log("could not get shared WirelessManager pointer"); 178 | } 179 | } 180 | } 181 | 182 | /*! 183 | * \brief Get the version of NickelDBus 184 | */ 185 | QString NDBDbus::ndbVersion() { 186 | return QStringLiteral(NH_VERSION); 187 | } 188 | 189 | /*! 190 | * \internal 191 | * \brief Set stackedWidget pointer to null if widget ever destroyed by Nickel 192 | */ 193 | void NDBDbus::handleStackedWidgetDestroyed() { 194 | stackedWidget = nullptr; 195 | } 196 | 197 | /*! 198 | * \internal 199 | * \brief Handle the QStackedWidget currentChanged event 200 | * 201 | * \a index is the index of the new widget. 202 | */ 203 | void NDBDbus::handleQSWCurrentChanged(int index) { 204 | if (index >= 0) { 205 | // I'd rather emit the ndbViewChanged signal here, but it's 206 | // not reliable, so it seems it needs to wait until the signal 207 | // handler completes. Hence the timer. 208 | // This does give us a chance to filter out duplicate change 209 | // signals, as some firmware versions appear to do. 210 | if (!viewTimer->isActive()) { 211 | viewTimer->start(10); 212 | } 213 | } 214 | } 215 | 216 | /*! 217 | * \internal 218 | * \brief Emits ndbViewChanged() after a small timeout 219 | */ 220 | void NDBDbus::handleQSWTimer() { 221 | emit ndbViewChanged(ndbCurrentView()); 222 | } 223 | 224 | /*! 225 | * \brief Get the class name of the current view. 226 | * 227 | * Some class name examples are \c HomePageView \c ReadingView 228 | * among others. 229 | */ 230 | QString NDBDbus::ndbCurrentView() { 231 | QString name = QString(); 232 | NDB_DBUS_SYM_ASSERT(name, nSym.MainWindowController_sharedInstance); 233 | NDB_DBUS_SYM_ASSERT(name, nSym.MainWindowController_currentView); 234 | MainWindowController *mwc = nSym.MainWindowController_sharedInstance(); 235 | NDB_DBUS_ASSERT(name, QDBusError::InternalError, mwc, "unable to get shared MainWindowController instance"); 236 | QWidget *cv = nSym.MainWindowController_currentView(mwc); 237 | NDB_DBUS_ASSERT(name, QDBusError::InternalError, cv, "unable to get current view from MainWindowController"); 238 | if (!stackedWidget) { 239 | if (QString(cv->parentWidget()->metaObject()->className()) == "QStackedWidget") { 240 | stackedWidget = static_cast(cv->parentWidget()); 241 | QObject::connect(stackedWidget, &QStackedWidget::currentChanged, this, &NDBDbus::handleQSWCurrentChanged); 242 | QObject::connect(stackedWidget, &QObject::destroyed, this, &NDBDbus::handleStackedWidgetDestroyed); 243 | } else { 244 | nh_log("expected QStackedWidget, got %s", cv->parentWidget()->metaObject()->className()); 245 | } 246 | } 247 | name = cv->objectName(); 248 | if (name == "N3Dialog") { 249 | NDB_DBUS_SYM_ASSERT(name, nSym.N3Dialog__content); 250 | if (QWidget *c = nSym.N3Dialog__content(cv)) { 251 | name = c->objectName(); 252 | } 253 | } else if (name == "ReadingView") { 254 | rvConnectSignals(cv); 255 | } 256 | return name; 257 | } 258 | 259 | bool NDBDbus::ndbInUSBMS() { 260 | return nSym.PlugManager__gadgetMode(nSym.PlugManager__sharedInstance()); 261 | } 262 | 263 | QString NDBDbus::getNickelMetaObjectDetails(const QMetaObject* nmo) { 264 | QString str = QStringLiteral(""); 265 | str.append(QString("Showing meta information for Nickel class %1 : \n").arg(nmo->className())); 266 | str.append("Properties : \n"); 267 | for (int i = nmo->propertyOffset(); i < nmo->propertyCount(); ++i) { 268 | QMetaProperty prop = nmo->property(i); 269 | str.append(QString("\t%1 %2 :: readable: %3 :: writeable: %4\n").arg(prop.typeName()).arg(prop.name()).arg(prop.isReadable()).arg(prop.isWritable())); 270 | } 271 | str.append("Methods : \n"); 272 | for (int i = nmo->methodOffset(); i < nmo->methodCount(); ++i) { 273 | QMetaMethod method = nmo->method(i); 274 | const char *method_type; 275 | switch (method.methodType()) { 276 | case QMetaMethod::Signal: 277 | method_type = "SIGNAL"; 278 | break; 279 | case QMetaMethod::Slot: 280 | method_type = "SLOT"; 281 | break; 282 | case QMetaMethod::Method: 283 | method_type = "METHOD"; 284 | break; 285 | case QMetaMethod::Constructor: 286 | method_type = "CONSTRUCTOR"; 287 | break; 288 | default: 289 | method_type = "UNKOWN"; 290 | } 291 | str.append(QString("\t%1 :: %2 %3\n").arg(method_type).arg(method.typeName()).arg(method.methodSignature().constData())); 292 | } 293 | return str; 294 | } 295 | 296 | /*! 297 | * \brief Print available details from nickel classes 298 | * 299 | * This method attempts to dlsym then parse the staticMetaObject 300 | * property available from the mangeled \a staticMetaobjectSymbol 301 | * 302 | * A formatted string of available signals and slots is returned. 303 | */ 304 | QString NDBDbus::ndbNickelClassDetails(QString const& staticMetaobjectSymbol) { 305 | NDB_DBUS_USB_ASSERT(""); 306 | typedef QMetaObject NickelMetaObject; 307 | NDB_DBUS_ASSERT("",QDBusError::InvalidArgs, staticMetaobjectSymbol.endsWith(QStringLiteral("staticMetaObjectE")), "not a valid staticMetaObject symbol"); 308 | QByteArray sym = staticMetaobjectSymbol.toLatin1(); 309 | NickelMetaObject *nmo; 310 | reinterpret_cast(nmo) = dlsym(libnickel, sym.constData()); 311 | NDB_DBUS_ASSERT("", QDBusError::InternalError, nmo, "could not dlsym staticMetaObject function for symbol %s", sym.constData()); 312 | return getNickelMetaObjectDetails((const NickelMetaObject*)nmo); 313 | } 314 | 315 | /*! 316 | * \brief Check if a signal was successfully connected 317 | * 318 | * Check if \a signalName is connected. \a signalName must be provided 319 | * without parentheses and parameters. 320 | * 321 | * Returns \c 1 if exists, or \c 0 otherwise 322 | */ 323 | bool NDBDbus::ndbSignalConnected(QString const &signalName) { 324 | return connectedSignals.contains(signalName); 325 | } 326 | 327 | /*! 328 | * \internal 329 | * \brief Print details gleaned from the QApplication instance 330 | */ 331 | QString NDBDbus::ndbNickelWidgets() { 332 | QString str = QString("Active Modal: \n"); 333 | QWidget *modal = QApplication::activeModalWidget(); 334 | if (modal) { 335 | str.append(QString("%1\n").arg(modal->metaObject()->className())); 336 | } 337 | str.append("\nActive Window: \n"); 338 | QWidget *window = QApplication::activeWindow(); 339 | if (window) { 340 | str.append(QString("%1\n").arg(window->metaObject()->className())); 341 | } 342 | str.append("\nFocused widget: \n"); 343 | QWidget *focus = QApplication::focusWidget(); 344 | if (focus) { 345 | str.append(QString("%1\n").arg(focus->metaObject()->className())); 346 | } 347 | str.append("\nAll Widgets: \n"); 348 | QWidgetList widgets = QApplication::allWidgets(); 349 | for (int i = 0; i < widgets.size(); ++i) { 350 | str.append(QString("%1\n").arg(widgets[i]->metaObject()->className())); 351 | } 352 | str.append("\nReading View State: \n"); 353 | QWidgetList visWidgets = QApplication::allWidgets(); 354 | for (int i = 0; i < visWidgets.size(); ++i) { 355 | if (!QString(visWidgets[i]->metaObject()->className()).compare("ReadingView")) { 356 | if (!visWidgets[i]->isHidden()) { 357 | str.append("visible\n"); 358 | } 359 | str.append("\nReadingView Hierachy: "); 360 | QWidget *w = visWidgets[i]; 361 | while (w) { 362 | str.append(QString("%1 -> ").arg(w->metaObject()->className())); 363 | w = w->parentWidget(); 364 | } 365 | str.append("\n"); 366 | } 367 | } 368 | str.append("\nStacked Widgets: \n"); 369 | for (int i = 0; i < visWidgets.size(); ++i) { 370 | if (!QString(visWidgets[i]->metaObject()->className()).compare("QStackedWidget")) { 371 | str.append("\nWidgets in Stack: \n"); 372 | QStackedWidget *sw = static_cast(visWidgets[i]); 373 | for (int j = 0; j < sw->count(); ++j) { 374 | if (QWidget *w = sw->widget(j)) { 375 | str.append(QString("%1\n").arg(w->metaObject()->className())); 376 | } 377 | } 378 | } 379 | } 380 | 381 | // foreach (QWidget *widget, QApplication::topLevelWidgets()) { 382 | // if (!widget->isHidden()) 383 | // str.append("%1").arg(widget->metaObject()->className()); 384 | // } 385 | return str; 386 | } 387 | 388 | /*! 389 | * \brief Get the current firmware version 390 | * 391 | * Get the current firmware version as found in the user agent string 392 | */ 393 | QString NDBDbus::ndbFirmwareVersion() { 394 | NDB_DBUS_USB_ASSERT(fwVersion); 395 | if (fwVersion.isEmpty()) { 396 | NDB_DBUS_SYM_ASSERT(fwVersion, nSym.Device__getCurrentDevice); 397 | NDB_DBUS_SYM_ASSERT(fwVersion, nSym.Device__userAgent); 398 | Device *d = nSym.Device__getCurrentDevice(); 399 | NDB_DBUS_ASSERT(fwVersion, QDBusError::InternalError, d, "unable to get current device"); 400 | QString ua = QString::fromUtf8(nSym.Device__userAgent(d)); 401 | QRegExp fwRegex = QRegExp("^.+\\(Kobo Touch (\\d+)/([\\d\\.]+)\\)$"); 402 | NDB_DBUS_ASSERT(fwVersion, QDBusError::InternalError, (fwRegex.indexIn(ua) != -1 && fwRegex.captureCount() == 2), "could not get fw version from ua string"); 403 | fwVersion = fwRegex.cap(2); 404 | } 405 | return fwVersion; 406 | } 407 | 408 | #define NDB_DLG_ASSERT(ret, cond) NDB_DBUS_ASSERT(ret, QDBusError::InternalError, cond, (cfmDlg->errString.toUtf8().constData())) 409 | 410 | /*! 411 | * \internal 412 | * \brief Utility method to create one of the preset dialogs 413 | */ 414 | enum Result NDBDbus::dlgConfirmCreatePreset(QString const& title, QString const& body, QString const& acceptText, QString const& rejectText) { 415 | enum Result res; 416 | NDB_ASSERT_RES(res, cfmDlg->createDialog(NDBCfmDlg::TypeStd)); 417 | if (!title.isEmpty()) { NDB_ASSERT_RES(res, cfmDlg->setTitle(title)); } 418 | if (!body.isEmpty()) { NDB_ASSERT_RES(res, cfmDlg->setBody(body)); } 419 | if (!rejectText.isEmpty()) { NDB_ASSERT_RES(res, cfmDlg->setReject(rejectText)); } 420 | if (!acceptText.isEmpty()) { NDB_ASSERT_RES(res, cfmDlg->setAccept(acceptText)); } 421 | QObject::connect(cfmDlg->dlg, &QDialog::finished, this, &NDBDbus::dlgConfirmResult); 422 | NDB_ASSERT_RES(res, cfmDlg->showDialog()); 423 | return Ok; 424 | } 425 | 426 | /*! 427 | * \brief Show a confirmation dialog with no buttons (except close) 428 | * 429 | * Create a dialog box with \a title and \a body. This dialog only has a close 430 | * button. 431 | * 432 | * When the dialog is closed, a \l dlgConfirmResult() signal is emitted. 433 | */ 434 | void NDBDbus::dlgConfirmNoBtn(QString const& title, QString const& body) { 435 | NDB_DBUS_USB_ASSERT((void) 0); 436 | NDB_DLG_ASSERT((void) 0, (dlgConfirmCreatePreset(title, body, "", "") == Ok)); 437 | } 438 | 439 | /*! 440 | * \brief Show a confirmation dialog with accept and close buttons 441 | * 442 | * Create a dialog box with \a title and \a body. This dialog has a close 443 | * button, and an accept button labeled with \a acceptText 444 | * 445 | * When the dialog is closed, or the accept button is pressed, a 446 | * \l dlgConfirmResult() signal is emitted. 447 | */ 448 | void NDBDbus::dlgConfirmAccept(QString const& title, QString const& body, QString const& acceptText) { 449 | NDB_DBUS_USB_ASSERT((void) 0); 450 | NDB_DLG_ASSERT((void) 0, (dlgConfirmCreatePreset(title, body, acceptText, "") == Ok)); 451 | } 452 | 453 | /*! 454 | * \brief Show a confirmation dialog with reject and close buttons 455 | * 456 | * Create a dialog box with \a title and \a body. This dialog has a close 457 | * button, and a reject button labeled with \a rejectText 458 | * 459 | * When the dialog is closed, or the reject button is pressed, a 460 | * \l dlgConfirmResult() signal is emitted. 461 | */ 462 | void NDBDbus::dlgConfirmReject(QString const& title, QString const& body, QString const& rejectText) { 463 | NDB_DBUS_USB_ASSERT((void) 0); 464 | NDB_DLG_ASSERT((void) 0, (dlgConfirmCreatePreset(title, body, "", rejectText) == Ok)); 465 | } 466 | 467 | /*! 468 | * \brief Show a confirmation dialog with reject and close buttons 469 | * 470 | * Create a dialog box with \a title and \a body. This dialog has a close 471 | * button, a reject button labeled with \a rejectText, and an accept 472 | * button labeled with \a acceptText. 473 | * 474 | * When the dialog is closed, either button is pressed, a 475 | * \l dlgConfirmResult() signal is emitted. 476 | */ 477 | void NDBDbus::dlgConfirmAcceptReject(QString const& title, QString const& body, QString const& acceptText, QString const& rejectText) { 478 | NDB_DBUS_USB_ASSERT((void) 0); 479 | NDB_DLG_ASSERT((void) 0, (dlgConfirmCreatePreset(title, body, acceptText, rejectText) == Ok)); 480 | } 481 | 482 | /*! 483 | * \brief Create a flexible confirmation dialog 484 | * 485 | * Create (but not show) a flexible confirmation dialog. If \a createLineEdit is 486 | * \c true a LineEdit dialog will be created, otherwise a standard dialog is created. 487 | * 488 | * The caller can invoke \l dlgConfirmSetTitle(), \l dlgConfirmSetBody(), 489 | * \l dlgConfirmSetAccept(), \l dlgConfirmSetReject(), \l dlgConfirmSetModal(), 490 | * \l dlgConfirmShowClose(), \l dlgConfirmSetProgress() to customise the appearance and 491 | * behaviour of the dialog. If the dialog is a LineEdit, \l dlgConfirmSetLEPassword() and 492 | * \l dlgConfirmSetLEPlaceholder() can also be called. 493 | * 494 | * Show the dialog by calling \l dlgConfirmShow(). It can be closed by calling 495 | * \l dlgConfirmClose() in addition to the user closing it. 496 | * 497 | * \l dlgConfirmResult() signal is emitted when the dialog is closed. 498 | * 499 | * For a LineEdit dialog, if the dialog is closed by tapping the 'accept' button, the 500 | * \l dlgConfirmTextInput() signal will emit the contents of the text edit field 501 | * (which may be an empty string), and \l dlgConfirmResult() will emit \c 1. 502 | * Otherwise, \l dlgConfirmResult() will emit the result of \c 0 and \l dlgConfirmTextInput() 503 | * will emit an empty string. 504 | * 505 | * \since 0.2.0 506 | */ 507 | void NDBDbus::dlgConfirmCreate(bool createLineEdit) { 508 | NDB_DBUS_USB_ASSERT((void) 0); 509 | NDB_DLG_ASSERT((void) 0, (cfmDlg->createDialog(createLineEdit ? NDBCfmDlg::TypeLineEdit : NDBCfmDlg::TypeStd) == Ok)); 510 | if (createLineEdit) { 511 | QObject::connect(cfmDlg->dlg, &QDialog::accepted, this, &NDBDbus::onDlgLineEditAccepted); 512 | QObject::connect(cfmDlg->dlg, &QDialog::rejected, this, &NDBDbus::onDlgLineEditRejected); 513 | } else { 514 | QObject::connect(cfmDlg->dlg, &QDialog::finished, this, &NDBDbus::dlgConfirmResult); 515 | } 516 | } 517 | 518 | /*! 519 | * \brief Set title of an existing confirmation dialog 520 | * 521 | * The confirmation dialog will have the title set to \a title 522 | * 523 | * \since 0.2.0 524 | */ 525 | void NDBDbus::dlgConfirmSetTitle(QString const& title) { 526 | NDB_DBUS_USB_ASSERT((void) 0); 527 | NDB_DLG_ASSERT((void) 0, (cfmDlg->setTitle(title) == Ok)); 528 | } 529 | 530 | /*! 531 | * \brief Set body text of an existing confirmation dialog 532 | * 533 | * The confirmation dialog will have the body text set to \a body 534 | * 535 | * \since 0.2.0 536 | */ 537 | void NDBDbus::dlgConfirmSetBody(QString const& body) { 538 | NDB_DBUS_USB_ASSERT((void) 0); 539 | NDB_DLG_ASSERT((void) 0, (cfmDlg->setBody(body) == Ok)); 540 | } 541 | 542 | /*! 543 | * \brief Set the accept button of an existing confirmation dialog 544 | * 545 | * The accept button will be enabled, and its label will be set 546 | * to \a acceptText 547 | * 548 | * \since 0.2.0 549 | */ 550 | void NDBDbus::dlgConfirmSetAccept(QString const& acceptText) { 551 | NDB_DBUS_USB_ASSERT((void) 0); 552 | NDB_DLG_ASSERT((void) 0, (cfmDlg->setAccept(acceptText) == Ok)); 553 | } 554 | 555 | /*! 556 | * \brief Set the reject button of an existing confirmation dialog 557 | * 558 | * The reject button will be enabled, and its label will be set 559 | * to \a rejectText 560 | * 561 | * \since 0.2.0 562 | */ 563 | void NDBDbus::dlgConfirmSetReject(QString const& rejectText) { 564 | NDB_DBUS_USB_ASSERT((void) 0); 565 | NDB_DLG_ASSERT((void) 0, (cfmDlg->setReject(rejectText) == Ok)); 566 | } 567 | 568 | /*! 569 | * \brief Set whether the confirmation dialog will be modal 570 | * 571 | * If \a modal is \c true the user will not be able to exit 572 | * the dialog by tapping outside it. 573 | * 574 | * \since 0.2.0 575 | */ 576 | void NDBDbus::dlgConfirmSetModal(bool modal) { 577 | NDB_DBUS_USB_ASSERT((void) 0); 578 | NDB_DLG_ASSERT((void) 0, (cfmDlg->setModal(modal) == Ok)); 579 | } 580 | 581 | /*! 582 | * \brief Set whether the confirmation dialog will have a close button 583 | * 584 | * If \a show is \c false the show button will not be displayed. 585 | * Note, if the dialog is modal, and accept and reject buttons are 586 | * not set, the user will have no means of closing the dialog. 587 | * 588 | * \since 0.2.0 589 | */ 590 | void NDBDbus::dlgConfirmShowClose(bool show) { 591 | NDB_DBUS_USB_ASSERT((void) 0); 592 | NDB_DLG_ASSERT((void) 0, (cfmDlg->showClose(show) == Ok)); 593 | } 594 | 595 | /*! 596 | * \brief Display a progress bar on the currently open dialog 597 | * 598 | * Displays a progress bar with a range from \a min to \a max, and sets the 599 | * current value to \a val. If any one of \a min \a max or \a val are set 600 | * to \c -1, the progress bar will be hidden. 601 | * 602 | * If set, \a format determines how the label will be displayed. It uses 603 | * the same placeholders as a QProgressBar. The placeholders are \c %p for 604 | * percentage value, \c %v for current step, \c %m for last step. The default 605 | * if not set is \c %p%. 606 | * 607 | * \since 0.2.0 608 | */ 609 | void NDBDbus::dlgConfirmSetProgress(int min, int max, int val, QString const& format) { 610 | NDB_DBUS_USB_ASSERT((void) 0); 611 | NDB_DLG_ASSERT((void) 0, (cfmDlg->setProgress(min, max, val, format) == Ok)); 612 | } 613 | 614 | /*! 615 | * \brief Sets whether the current line edit dialog is a password dialog 616 | * 617 | * If \a password is \c true the dialog will have a 'show password' checkbox, and 618 | * input text will be masked if that checkbox is not checked. 619 | * 620 | * \since 0.2.0 621 | */ 622 | void NDBDbus::dlgConfirmSetLEPassword(bool password) { 623 | NDB_DBUS_USB_ASSERT((void) 0); 624 | NDB_DLG_ASSERT((void) 0, (cfmDlg->setLEPassword(password) == Ok)); 625 | } 626 | 627 | /*! 628 | * \brief Add placeholder text to a line edit dialog 629 | * 630 | * Set the line edit placeholder to \a placeholder 631 | * 632 | * \since 0.2.0 633 | */ 634 | void NDBDbus::dlgConfirmSetLEPlaceholder(QString const& placeholder) { 635 | NDB_DBUS_USB_ASSERT((void) 0); 636 | NDB_DLG_ASSERT((void) 0, (cfmDlg->setLEPlaceholder(placeholder) == Ok)); 637 | } 638 | 639 | /*! 640 | * \brief Display the current dialog 641 | * 642 | * \since 0.2.0 643 | */ 644 | void NDBDbus::dlgConfirmShow() { 645 | NDB_DBUS_USB_ASSERT((void) 0); 646 | NDB_DLG_ASSERT((void) 0, (cfmDlg->showDialog() == Ok)); 647 | } 648 | 649 | /*! 650 | * \brief Close the currently opened dialog 651 | * 652 | * Closes the currently open dialog. Will return an 653 | * error if the dialog has already been closed by the user. 654 | * 655 | * \since 0.2.0 656 | */ 657 | void NDBDbus::dlgConfirmClose() { 658 | NDB_DBUS_USB_ASSERT((void) 0); 659 | NDB_DLG_ASSERT((void) 0, (cfmDlg->closeDialog() == Ok)); 660 | } 661 | 662 | /*! 663 | * \internal 664 | * \brief slot for handling a line edit dialog that is accepted. 665 | */ 666 | void NDBDbus::onDlgLineEditAccepted() { 667 | emit dlgConfirmTextInput(cfmDlg->getLEText()); 668 | emit dlgConfirmResult(QDialog::Accepted); 669 | } 670 | 671 | /*! 672 | * \internal 673 | * \brief slot for handling a line edit dialog that is rejected. 674 | */ 675 | void NDBDbus::onDlgLineEditRejected() { 676 | emit dlgConfirmTextInput(""); 677 | emit dlgConfirmResult(QDialog::Rejected); 678 | } 679 | 680 | /*! 681 | * \brief Show a small, temporary text box with a message 682 | * 683 | * Show a text box on screen for \a toastDuration duration (in milliseconds) 684 | * with \a msgMain as the body text, and an optional \a msgSub 685 | */ 686 | void NDBDbus::mwcToast(int toastDuration, QString const &msgMain, QString const &msgSub) { 687 | NDB_DBUS_USB_ASSERT((void) 0); 688 | // The following code has been adapted from NickelMenu 689 | NDB_DBUS_ASSERT((void) 0, QDBusError::InvalidArgs, toastDuration > 0 && toastDuration <= 5000, "toast duration must be between 0 and 5000 miliseconds"); 690 | NDB_DBUS_SYM_ASSERT((void) 0, nSym.MainWindowController_sharedInstance && nSym.MainWindowController_toast); 691 | MainWindowController *mwc = nSym.MainWindowController_sharedInstance(); 692 | NDB_DBUS_ASSERT((void) 0, QDBusError::InternalError, mwc, "could not get MainWindowController instance"); 693 | nSym.MainWindowController_toast(mwc, msgMain, msgSub, toastDuration); 694 | } 695 | 696 | /*! 697 | * \brief Navigate to the home screen 698 | */ 699 | void NDBDbus::mwcHome() { 700 | NDB_DBUS_USB_ASSERT((void) 0); 701 | return ndbNickelMisc("home"); 702 | } 703 | 704 | /*! 705 | * \brief Begin an abbreviated book rescan. Same as 'rescan_books' from NickelMenu 706 | */ 707 | void NDBDbus::pfmRescanBooks() { 708 | NDB_DBUS_USB_ASSERT((void) 0); 709 | return ndbNickelMisc("rescan_books"); 710 | } 711 | 712 | /*! 713 | * \brief Begins a full book rescan. Same as 'rescan_books_full' from NickelMenu 714 | */ 715 | void NDBDbus::pfmRescanBooksFull() { 716 | NDB_DBUS_USB_ASSERT((void) 0); 717 | return ndbNickelMisc("rescan_books_full"); 718 | } 719 | 720 | /*! 721 | * \brief Begins a filesystem sync to add/remove content from onboard storage 722 | * 723 | * This is a more targeted option to add new content compared to \l pfmRescanBooks 724 | * and \l pfmRescanBooksFull. It is what the browser uses when downloading 725 | * ebook files. 726 | * 727 | * Emits \l fssGotNumFilesToProcess signal to specify the number of files 728 | * to be added, \l fssParseProgress to specify the current progress, and the 729 | * \l fssFinished signal is emitted when complete. 730 | * 731 | * \since 0.3.0 732 | */ 733 | void NDBDbus::n3fssSyncOnboard() { 734 | QStringList path("/mnt/onboard"); 735 | return n3fssSync(&path); 736 | } 737 | 738 | /*! 739 | * \brief Begins a filesystem sync to add/remove content from sd storage 740 | * 741 | * This is a more targeted option to add new content compared to \l pfmRescanBooks 742 | * and \l pfmRescanBooksFull. It is what the browser uses when downloading 743 | * ebook files. 744 | * 745 | * Emits \l fssGotNumFilesToProcess signal to specify the number of files 746 | * to be added, \l fssParseProgress to specify the current progress, and the 747 | * \l fssFinished signal is emitted when complete. 748 | * 749 | * \since 0.3.0 750 | */ 751 | void NDBDbus::n3fssSyncSD() { 752 | QStringList path("/mnt/sd"); 753 | return n3fssSync(&path); 754 | } 755 | 756 | /*! 757 | * \brief Begins a filesystem sync to add/remove content from onboard and sd storage 758 | * 759 | * This is a more targeted option to add new content compared to \l pfmRescanBooks 760 | * and \l pfmRescanBooksFull. It is what the browser uses when downloading 761 | * ebook files. 762 | * 763 | * Emits \l fssGotNumFilesToProcess signal to specify the number of files 764 | * to be added, \l fssParseProgress to specify the current progress, and the 765 | * \l fssFinished signal is emitted when complete. 766 | * 767 | * \since 0.3.0 768 | */ 769 | void NDBDbus::n3fssSyncBoth() { 770 | QStringList paths = QStringList() << "/mnt/onboard" << "/mnt/sd"; 771 | return n3fssSync(&paths); 772 | } 773 | 774 | void NDBDbus::n3fssSync(QStringList* paths) { 775 | NDB_DBUS_USB_ASSERT((void) 0); 776 | NDB_DBUS_ASSERT((void) 0, QDBusError::InternalError, 777 | nSym.N3FSSyncManager__sharedInstance && nSym.N3FSSyncManager__sync, "no N3FSSyncManager symbols"); 778 | N3FSSyncManager* n3fssm = nSym.N3FSSyncManager__sharedInstance(); 779 | NDB_DBUS_ASSERT((void) 0, QDBusError::InternalError, n3fssm, "could not get N3FSSyncManager::sharedInstance()"); 780 | QObject::connect(n3fssm, SIGNAL(finished()), this, SIGNAL(fssFinished()), Qt::UniqueConnection); 781 | QObject::connect(n3fssm, SIGNAL(gotNumFilesToProcess(int)), this, SIGNAL(fssGotNumFilesToProcess(int)), Qt::UniqueConnection); 782 | QObject::connect(n3fssm, SIGNAL(parseProgress(int)), this, SIGNAL(fssParseProgress(int)), Qt::UniqueConnection); 783 | return nSym.N3FSSyncManager__sync(n3fssm, paths); 784 | } 785 | 786 | void NDBDbus::ndbNickelMisc(const char *action) { 787 | nm_action_result_t *res = nm_action_nickel_misc(action); 788 | if (!res) { 789 | nh_log("nm_action_nickel_misc failed with error: %s", nm_err_peek()); 790 | sendErrorReply(QDBusError::InternalError, QString("nm_action_nickel_misc failed with error: %1").arg(nm_err())); 791 | return; 792 | } 793 | nm_action_result_free(res); 794 | } 795 | 796 | bool NDBDbus::ndbActionStrValid(QString const& actStr) { 797 | return (!actStr.compare("enable") || !actStr.compare("disable") || !actStr.compare("toggle")); 798 | } 799 | 800 | /*! 801 | * \brief Connect to WiFi network. 802 | * 803 | * Note, this is the same as 'autoconnect' option from NickelMenu 804 | */ 805 | void NDBDbus::wfmConnectWireless() { 806 | NDB_DBUS_USB_ASSERT((void) 0); 807 | return ndbWireless("autoconnect"); 808 | } 809 | 810 | /*! 811 | * \brief Connect silently to WiFi network. 812 | * 813 | * Note, this is the same as 'autoconnect_silent' from NickelMenu 814 | */ 815 | void NDBDbus::wfmConnectWirelessSilently() { 816 | NDB_DBUS_USB_ASSERT((void) 0); 817 | return ndbWireless("autoconnect_silent"); 818 | } 819 | 820 | /*! 821 | * \brief Enable/disable/toggle WiFi. Same as NickelMenu WiFi 'enable'/'disable'/'toggle' options 822 | * 823 | * Note, this is the same as NickelMenu WiFi 'enable'/'disable'/'toggle' options. 824 | * 825 | * \a action should be one of \c {enable}, \c {disable}, \c {toggle} 826 | */ 827 | void NDBDbus::wfmSetAirplaneMode(QString const& action) { 828 | NDB_DBUS_USB_ASSERT((void) 0); 829 | NDB_DBUS_ASSERT((void) 0, QDBusError::InvalidArgs, ndbActionStrValid(action), "invalid action name"); 830 | QByteArray actBytes = action.toUtf8(); 831 | return ndbWireless(actBytes.constData()); 832 | } 833 | 834 | void NDBDbus::ndbWireless(const char *act) { 835 | nm_action_result_t *res = nm_action_nickel_wifi(act); 836 | if (!res) { 837 | nh_log("ndbWireless failed with error: %s", nm_err_peek()); 838 | sendErrorReply(QDBusError::InternalError, QString("ndbWireless failed with error: %1").arg(nm_err())); 839 | return; 840 | } 841 | nm_action_result_free(res); 842 | } 843 | 844 | void NDBDbus::onWWAboutToKillWifi(PermissionRequest* allow) { 845 | if (allow != nullptr) { 846 | NDB_DEBUG("WirelessWatchdog wants to kill Wifi. Denying request."); 847 | *allow = false; 848 | } 849 | return; 850 | } 851 | 852 | /*! 853 | * \brief Keep Wifi connection alive 854 | * 855 | * Prevents Nickel from killing the Wifi connection after a short amount of time. 856 | * Set \a keepalive to \c true to enable the keepalive, and \c false to disable it. 857 | * It is best to only keep Wifi enabled as long as necessary. 858 | * 859 | * \since 0.3.0 860 | */ 861 | void NDBDbus::ndbWifiKeepalive(bool keepalive) { 862 | NDB_DBUS_USB_ASSERT((void) 0); 863 | NDB_DBUS_ASSERT((void) 0, QDBusError::InternalError, nSym.WirelessWatchdog__sharedInstance, "no WirelessWatchdog::sharedInstance() symbol"); 864 | WirelessWatchdog *wd = nSym.WirelessWatchdog__sharedInstance(); 865 | NDB_DBUS_ASSERT((void) 0, QDBusError::InternalError, wd, "could not get WirelessWatchdog::sharedInstance()"); 866 | if (keepalive) { 867 | QObject::connect(wd, SIGNAL(aboutToKillWifi(PermissionRequest*)), this, SLOT(onWWAboutToKillWifi(PermissionRequest*)), Qt::UniqueConnection); 868 | } else { 869 | QObject::disconnect(wd, SIGNAL(aboutToKillWifi(PermissionRequest*)), this, SLOT(onWWAboutToKillWifi(PermissionRequest*))); 870 | } 871 | return; 872 | } 873 | 874 | /*! 875 | * \brief Open the web browser. 876 | * 877 | * Note, this is the same as the NickelMenu browser options 878 | * 879 | * Opens the web browser to the default homepage. if \a modal 880 | * is \c true then the browser will be opened as a modal box with 881 | * a close button. If \a url is set, the browser will open it on 882 | * open. If \a css is set, additional CSS is supplied to the browser 883 | */ 884 | void NDBDbus::bwmOpenBrowser(bool modal, QString const& url, QString const& css) { 885 | NDB_DBUS_USB_ASSERT((void) 0); 886 | QString qarg = QStringLiteral(""); 887 | if (modal || !url.isEmpty() || !css.isEmpty()) { 888 | if (modal) { 889 | qarg.append("modal"); 890 | if (!url.isEmpty() || !css.isEmpty()) { 891 | qarg.append(":"); 892 | } 893 | } 894 | if (!url.isEmpty()) { 895 | qarg.append(QString("%1 ").arg(url)); 896 | } 897 | if (!css.isEmpty()) { 898 | qarg.append(css); 899 | } 900 | } 901 | QByteArray qb_arg; 902 | if (!qarg.isEmpty()) { 903 | qb_arg = qarg.toUtf8(); 904 | } else { 905 | qb_arg = QByteArray(); 906 | } 907 | nm_action_result_t *res = nm_action_nickel_browser((qb_arg.isEmpty() ? NULL : qb_arg.constData())); 908 | if (!res) { 909 | nh_log("bwmOpenBrowser failed with error: %s", nm_err_peek()); 910 | sendErrorReply(QDBusError::InternalError, QString("bwmOpenBrowser failed with error: %1").arg(nm_err())); 911 | return; 912 | } 913 | nm_action_result_free(res); 914 | } 915 | 916 | /*! 917 | * \brief Invert the screen 918 | * 919 | * Set \a action to \c {enable}, \c {disable} or \c {toggle} inversion. 920 | */ 921 | void NDBDbus::nsInvert(QString const& action) { 922 | NDB_DBUS_USB_ASSERT((void) 0); 923 | return ndbSettings(action, "invert"); 924 | } 925 | 926 | /*! 927 | * \brief Set Dark Mode 928 | * 929 | * Set \a action to \c {enable}, \c {disable} or \c {toggle} dark mode 930 | */ 931 | void NDBDbus::nsDarkMode(QString const& action) { 932 | NDB_DBUS_USB_ASSERT((void) 0); 933 | return ndbSettings(action, "dark_mode"); 934 | } 935 | 936 | /*! 937 | * \brief Set UnlockEnabled 938 | * 939 | * Set \a action to \c {enable}, \c {disable} or \c {toggle} UnlockEnabled. 940 | */ 941 | void NDBDbus::nsLockscreen(QString const& action) { 942 | NDB_DBUS_USB_ASSERT((void) 0); 943 | return ndbSettings(action, "lockscreen"); 944 | } 945 | 946 | /*! 947 | * \brief Set screenshot setting 948 | * 949 | * Set \a action to \c {enable}, \c {disable} or \c {toggle} screenshots. 950 | */ 951 | void NDBDbus::nsScreenshots(QString const& action) { 952 | NDB_DBUS_USB_ASSERT((void) 0); 953 | return ndbSettings(action, "screenshots"); 954 | } 955 | 956 | /*! 957 | * \brief Sets the developer ForceWifiOn setting 958 | * 959 | * Set \a action to \c {enable}, \c {disable} or \c {toggle} ForceWifiOn. 960 | */ 961 | void NDBDbus::nsForceWifi(QString const& action) { 962 | NDB_DBUS_USB_ASSERT((void) 0); 963 | return ndbSettings(action, "force_wifi"); 964 | } 965 | 966 | /*! 967 | * \brief Sets the auto USB connect setting 968 | * 969 | * Set \a action to \c {enable}, \c {disable} or \c {toggle} auto USB connect. 970 | */ 971 | void NDBDbus::nsAutoUSBGadget(QString const& action) { 972 | NDB_DBUS_USB_ASSERT((void) 0); 973 | return ndbSettings(action, "auto_usb_gadget"); 974 | } 975 | 976 | void NDBDbus::ndbSettings(QString const& action, const char* setting) { 977 | NDB_DBUS_ASSERT((void) 0, QDBusError::InvalidArgs, ndbActionStrValid(action), "invalid action name"); 978 | QByteArray qarg = QString("%1:%2").arg(action).arg(setting).toUtf8(); 979 | nm_action_result_t *res = nm_action_nickel_setting(qarg.constData()); 980 | if (!res) { 981 | nh_log("ndbSettings failed with error: %s", nm_err()); 982 | sendErrorReply(QDBusError::InternalError, QString("ndbSettings failed with error: %1").arg(nm_err())); 983 | return; 984 | } 985 | nm_action_result_free(res); 986 | } 987 | 988 | /*! 989 | * \brief Shutdown Kobo 990 | */ 991 | void NDBDbus::pwrShutdown() { 992 | NDB_DBUS_USB_ASSERT((void) 0); 993 | return pwrAction("shutdown"); 994 | } 995 | 996 | /*! 997 | * \brief Reboot Kobo 998 | */ 999 | void NDBDbus::pwrReboot() { 1000 | NDB_DBUS_USB_ASSERT((void) 0); 1001 | return pwrAction("reboot"); 1002 | } 1003 | 1004 | /*! 1005 | * \brief Put Kobo to sleep 1006 | * 1007 | * \since 0.2.0 1008 | */ 1009 | void NDBDbus::pwrSleep() { 1010 | NDB_DBUS_USB_ASSERT((void) 0); 1011 | return pwrAction("sleep"); 1012 | } 1013 | 1014 | void NDBDbus::pwrAction(const char *action) { 1015 | nm_action_result_t *res = nm_action_power(action); 1016 | if (!res) { 1017 | nh_log("pwrAction failed with error: %s", nm_err_peek()); 1018 | sendErrorReply(QDBusError::InternalError, QString("pwrAction failed with error: %1").arg(nm_err())); 1019 | return; 1020 | } 1021 | nm_action_result_free(res); 1022 | } 1023 | 1024 | void NDBDbus::rvConnectSignals(QWidget* rv) { 1025 | // Just connecting pageChanged(int) for now. Others may or may not 1026 | // come in the future. 1027 | QObject::connect(rv, SIGNAL(pageChanged(int)), this, SIGNAL(rvPageChanged(int)), Qt::UniqueConnection); 1028 | } 1029 | 1030 | /*! 1031 | * \brief Gets the image size for the device 1032 | * 1033 | * Valid strings for \a type are \c N3_FULL , \c N3_LIBRARY_FULL , \c N3_LIBRARY_GRID 1034 | * 1035 | * Returns a string in the form \c "width \c height" 1036 | * 1037 | * \since 0.3.0 1038 | */ 1039 | QString NDBDbus::imgSizeForType(QString const& type) { 1040 | QString default_ret("-1 -1"); 1041 | NDB_DBUS_USB_ASSERT(default_ret); 1042 | NDB_DBUS_SYM_ASSERT(default_ret, nSym.Image__sizeForType); 1043 | bool type_valid = (type == "N3_FULL" || type == "N3_LIBRARY_FULL" || type == "N3_LIBRARY_GRID"); 1044 | NDB_DBUS_ASSERT(default_ret, QDBusError::InvalidArgs, type_valid, "invalid type name. Must be one of N3_FULL, N3_LIBRARY_FULL, N3_LIBRARY_GRID"); 1045 | NDB_DBUS_SYM_ASSERT(default_ret, nSym.Device__getCurrentDevice); 1046 | Device *d = nSym.Device__getCurrentDevice(); 1047 | NDB_DBUS_ASSERT(default_ret, QDBusError::InternalError, d, "unable to get current device"); 1048 | QSize img_size = nSym.Image__sizeForType(d, type); 1049 | return QString("%1 %2").arg(img_size.width()).arg(img_size.height()); 1050 | } 1051 | 1052 | /* Enum Documentation */ 1053 | 1054 | /*! 1055 | * \enum NDB::Result 1056 | * 1057 | * This enum stores the result status of a function or method 1058 | * 1059 | * \value Ok 1060 | * The function returned successfully without errors 1061 | * \value NotImplemented 1062 | * The function has no implementation 1063 | * \value InitError 1064 | * There was an error initialising an object 1065 | * \value SymbolError 1066 | * There was an error resolving a Nickel symbol 1067 | * \value NullError 1068 | * An unexpected nullptr was encountered 1069 | * \value ForbiddenError 1070 | * A function was called when not allowed to do so 1071 | * \value ParamError 1072 | * There was an error with a function parameter 1073 | * \value ConnError 1074 | * There was a dbus connection error 1075 | */ 1076 | 1077 | /* Signal Documentation */ 1078 | 1079 | /*! 1080 | * \fn void NDB::NDBDbus::dlgConfirmResult(int result) 1081 | * \brief The signal that is emitted when a confirmation dialog is dismissed 1082 | * 1083 | * When emitted, \a result will be \c 1 for ACCEPT or \c 0 for REJECT 1084 | */ 1085 | 1086 | /*! 1087 | * \fn void NDB::NDBDbus::dlgConfirmTextInput(QString input) 1088 | * \brief The signal that is emitted when text is entered by user 1089 | * 1090 | * When emitted \a input will be the text the user inputted. This signal is 1091 | * only emitted when the user taps the \c accept button is tapped. \a input 1092 | * may be an empty string. 1093 | * 1094 | * \since 0.2.0 1095 | */ 1096 | 1097 | /*! 1098 | * \fn void NDB::NDBDbus::pfmDoneProcessing() 1099 | * \brief The signal that nickel emits when the content import process has completed. 1100 | * 1101 | * The signal will be emitted following the content import triggered whenever 1102 | * the user unplugs from the computer, when \c rescan_books / \c rescan_books_full 1103 | * actions are triggered from NickelMenu, or when \l NDB::NDBDbus::pfmRescanBooks() 1104 | * or \l NDB::NDBDbus::pfmRescanBooksFull() methods are called from NDBDbus. 1105 | */ 1106 | 1107 | /*! 1108 | * \fn void NDB::NDBDbus::pfmAboutToConnect() 1109 | * \brief The signal that nickel emits when it is about to start the USB connection 1110 | */ 1111 | 1112 | /*! 1113 | * \fn void NDB::NDBDbus::wmTryingToConnect() 1114 | * \brief (todo: figure this out) 1115 | */ 1116 | 1117 | /*! 1118 | * \fn void NDB::NDBDbus::wmNetworkConnected() 1119 | * \brief This signal appears to be emitted when the network has successfully connected 1120 | * I'm unsure if this is emitted when the WiFi connects, or when a valid IP address 1121 | * is obtained. 1122 | */ 1123 | 1124 | /*! 1125 | * \fn void NDB::NDBDbus::wmNetworkDisconnected() 1126 | * \brief (todo: figure this out) 1127 | */ 1128 | 1129 | /*! 1130 | * \fn void NDB::NDBDbus::wmNetworkForgotten() 1131 | * \brief (todo: figure this out) 1132 | */ 1133 | 1134 | /*! 1135 | * \fn void NDB::NDBDbus::wmNetworkFailedToConnect() 1136 | * \brief (todo: figure this out) 1137 | */ 1138 | 1139 | /*! 1140 | * \fn void NDB::NDBDbus::wmScanningStarted() 1141 | * \brief (todo: figure this out) 1142 | */ 1143 | 1144 | /*! 1145 | * \fn void NDB::NDBDbus::wmScanningFinished() 1146 | * \brief (todo: figure this out) 1147 | */ 1148 | 1149 | /*! 1150 | * \fn void NDB::NDBDbus::wmScanningAborted() 1151 | * \brief (todo: figure this out) 1152 | */ 1153 | 1154 | /*! 1155 | * \fn void NDB::NDBDbus::wmWifiEnabled(bool enabled) 1156 | * \brief (todo: figure this out) 1157 | * 1158 | * Is wifi \a enabled ? 1159 | */ 1160 | 1161 | /*! 1162 | * \fn void NDB::NDBDbus::wmLinkQualityForConnectedNetwork(double quality) 1163 | * \brief (todo: figure this out) 1164 | * 1165 | * Shows the \a quality of the wifi signal 1166 | */ 1167 | 1168 | /*! 1169 | * \fn void NDB::NDBDbus::wmMacAddressAvailable(QString mac) 1170 | * \brief (todo: figure this out) 1171 | * 1172 | * \a mac address 1173 | */ 1174 | 1175 | /*! 1176 | * \fn void NDB::NDBDbus::ndbViewChanged(QString newView) 1177 | * \brief The signal that is emitted when the current view changes 1178 | * 1179 | * This signal is only emitted if \l NDB::NDBDbus::ndbCurrentView() has been called 1180 | * at least once by an application. \a newView is the class name of the new view. 1181 | * 1182 | * \sa NDB::NDBDbus::ndbCurrentView() 1183 | */ 1184 | 1185 | /*! 1186 | * \fn void NDB::NDBDbus::rvPageChanged(int pageNum) 1187 | * \brief The signal that is emitted when the current book changes page 1188 | * 1189 | * This signal is only emitted if \l NDB::NDBDbus::ndbCurrentView() has been called 1190 | * at least once by an application. \a pageNum is kepub or epub page 1191 | * number of the new page. 1192 | * 1193 | * \sa NDB::NDBDbus::ndbCurrentView() 1194 | */ 1195 | 1196 | } // namespace NDB 1197 | -------------------------------------------------------------------------------- /src/ndb/NDBDbus.h: -------------------------------------------------------------------------------- 1 | #ifndef NDB_DBUS_H 2 | #define NDB_DBUS_H 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include "NDBCfmDlg.h" 14 | 15 | typedef void PlugManager; 16 | typedef QObject PlugWorkflowManager; 17 | typedef QObject WirelessManager; 18 | typedef void MainWindowController; 19 | typedef QDialog ConfirmationDialog; 20 | typedef QWidget N3Dialog; 21 | typedef void Device; 22 | typedef QObject FSSyncManager; 23 | typedef FSSyncManager N3FSSyncManager; 24 | typedef bool PermissionRequest; 25 | typedef QObject WirelessWatchdog; 26 | 27 | #ifndef NDB_DBUS_IFACE_NAME 28 | #define NDB_DBUS_IFACE_NAME "com.github.shermp.nickeldbus" 29 | #endif 30 | #ifndef NDB_DBUS_OBJECT_PATH 31 | #define NDB_DBUS_OBJECT_PATH "/nickeldbus" 32 | #endif 33 | 34 | namespace NDB { 35 | 36 | class NDBDbus : public QObject, protected QDBusContext { 37 | Q_OBJECT 38 | Q_CLASSINFO("D-Bus Interface", NDB_DBUS_IFACE_NAME) 39 | 40 | QDBusConnection conn = QDBusConnection::systemBus(); 41 | 42 | public: 43 | bool initSucceeded; 44 | NDBDbus(QObject* parent); 45 | ~NDBDbus(); 46 | // bool registerDBus(); 47 | void connectSignals(); 48 | 49 | Q_SIGNALS: 50 | void dlgConfirmResult(int result); 51 | void dlgConfirmTextInput(QString input); 52 | // PlugworkFlowManager signals 53 | void pfmDoneProcessing(); 54 | void pfmAboutToConnect(); 55 | // FSSyncManager signals 56 | void fssFinished(); 57 | void fssGotNumFilesToProcess(int num); 58 | void fssParseProgress(int progress); 59 | // WirelessManager signals 60 | void wmTryingToConnect(); 61 | void wmNetworkConnected(); 62 | void wmNetworkDisconnected(); 63 | void wmNetworkForgotten(); 64 | void wmNetworkFailedToConnect(); 65 | void wmScanningStarted(); 66 | void wmScanningFinished(); 67 | void wmScanningAborted(); 68 | void wmWifiEnabled(bool enabled); 69 | void wmLinkQualityForConnectedNetwork(double quality); 70 | void wmMacAddressAvailable(QString mac); 71 | void ndbViewChanged(QString newView); 72 | void rvPageChanged(int pageNum); 73 | 74 | public Q_SLOTS: 75 | QString ndbVersion(); 76 | QString ndbNickelClassDetails(QString const& staticMmetaobjectSymbol); 77 | QString ndbNickelWidgets(); 78 | QString ndbCurrentView(); 79 | QString ndbFirmwareVersion(); 80 | // misc 81 | bool ndbSignalConnected(QString const& signalName); 82 | void mwcToast(int toastDuration, QString const& msgMain, QString const& msgSub = QStringLiteral("")); 83 | void mwcHome(); 84 | // Confirmation Dialogs 85 | void dlgConfirmNoBtn(QString const& title, QString const& body); 86 | void dlgConfirmAccept(QString const& title, QString const& body, QString const& acceptText); 87 | void dlgConfirmReject(QString const& title, QString const& body, QString const& rejectText); 88 | void dlgConfirmAcceptReject(QString const& title, QString const& body, QString const& acceptText, QString const& rejectText); 89 | // Flexi dialogs 90 | void dlgConfirmCreate(bool createLineEdit = false); 91 | void dlgConfirmSetTitle(QString const& title); 92 | void dlgConfirmSetBody(QString const& body); 93 | void dlgConfirmSetAccept(QString const& acceptText); 94 | void dlgConfirmSetReject(QString const& rejectText); 95 | void dlgConfirmSetModal(bool modal); 96 | void dlgConfirmShowClose(bool show); 97 | void dlgConfirmSetProgress(int min, int max, int val, QString const& format = ""); 98 | void dlgConfirmSetLEPassword(bool password); 99 | void dlgConfirmSetLEPlaceholder(QString const& placeholder); 100 | void dlgConfirmShow(); 101 | void dlgConfirmClose(); 102 | // PlugWorkFlowManager 103 | void pfmRescanBooks(); 104 | void pfmRescanBooksFull(); 105 | // N3FSSyncManager 106 | void n3fssSyncOnboard(); 107 | void n3fssSyncSD(); 108 | void n3fssSyncBoth(); 109 | // Wireless methods (WirelessFlowManager) 110 | void wfmConnectWireless(); 111 | void wfmConnectWirelessSilently(); 112 | void wfmSetAirplaneMode(QString const& action); 113 | // Wireless watchdog 114 | void ndbWifiKeepalive(bool keepalive); 115 | // Web Browser (BrowserWorkflowManager) 116 | void bwmOpenBrowser(bool modal = false, QString const& url = QString(), QString const& css = QString()); 117 | // Nickel Settings 118 | void nsInvert(QString const& action); 119 | void nsDarkMode(QString const& action); 120 | void nsLockscreen(QString const& action); 121 | void nsScreenshots(QString const& action); 122 | void nsForceWifi(QString const& action); 123 | void nsAutoUSBGadget(QString const& action); 124 | // Power commands 125 | void pwrShutdown(); 126 | void pwrReboot(); 127 | void pwrSleep(); 128 | // Image sizes 129 | QString imgSizeForType(QString const& type); 130 | protected Q_SLOTS: 131 | void handleQSWCurrentChanged(int index); 132 | void handleQSWTimer(); 133 | void handleStackedWidgetDestroyed(); 134 | void onDlgLineEditAccepted(); 135 | void onDlgLineEditRejected(); 136 | void onWWAboutToKillWifi(PermissionRequest* allow); 137 | private: 138 | void *libnickel; 139 | QSet connectedSignals; 140 | QStackedWidget *stackedWidget = nullptr; 141 | QString fwVersion; 142 | NDBCfmDlg *cfmDlg; 143 | //NDBN3Dlg *n3Dlg; 144 | struct { 145 | bool *(*PlugManager__gadgetMode)(PlugManager*); 146 | PlugManager *(*PlugManager__sharedInstance)(); 147 | PlugWorkflowManager *(*PlugWorkflowManager_sharedInstance)(); 148 | WirelessManager *(*WirelesManager_sharedInstance)(); 149 | MainWindowController *(*MainWindowController_sharedInstance)(); 150 | void (*MainWindowController_toast)(MainWindowController*, QString const&, QString const&, int); 151 | QWidget *(*MainWindowController_currentView)(MainWindowController*); 152 | QWidget* (*N3Dialog__content)(N3Dialog*); 153 | Device *(*Device__getCurrentDevice)(); 154 | QByteArray (*Device__userAgent)(Device*); 155 | QSize (*Image__sizeForType)(Device*, QString const&); 156 | N3FSSyncManager* (*N3FSSyncManager__sharedInstance)(); 157 | void (*N3FSSyncManager__sync)(N3FSSyncManager* _this, QStringList* paths); 158 | WirelessWatchdog* (*WirelessWatchdog__sharedInstance)(); 159 | } nSym; 160 | QTimer *viewTimer; 161 | bool ndbInUSBMS(); 162 | bool ndbActionStrValid(QString const& actStr); 163 | void ndbWireless(const char *act); 164 | void ndbSettings(QString const& action, const char* setting); 165 | void ndbNickelMisc(const char *action); 166 | QString getNickelMetaObjectDetails(const QMetaObject* nmo); 167 | template 168 | void ndbConnectSignal(T *srcObj, const char *srcSignal, const char *dest); 169 | void pwrAction(const char *action); 170 | void rvConnectSignals(QWidget* rv); 171 | void dlgConfirmLineEditFull(QString const& title, QString const& acceptText, QString const& rejectText, bool isPassword, QString const& setText); 172 | enum Result dlgConfirmCreatePreset(QString const& title, QString const& body, QString const& acceptText, QString const& rejectText); 173 | void n3fssSync(QStringList* paths); 174 | }; 175 | 176 | } // namespace NDB 177 | 178 | #endif // NDB_DBUS_H 179 | -------------------------------------------------------------------------------- /src/ndb/NDBWidgets.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include "NDBWidgets.h" 3 | 4 | namespace NDB { 5 | 6 | /*! 7 | * \brief Create a progress bar 8 | */ 9 | NDBProgressBar::NDBProgressBar(QWidget *parent, Qt::WindowFlags f) 10 | : QWidget(parent, f) 11 | { 12 | auto layout = new QHBoxLayout(); 13 | prog = new QProgressBar(this); 14 | label = new QLabel(this); 15 | layout->addWidget(prog); 16 | layout->addWidget(label); 17 | prog->setStyleSheet(QString(R"( 18 | QProgressBar:horizontal { 19 | border: 1px solid gray; 20 | background: white; 21 | padding: 1px; 22 | } 23 | QProgressBar::chunk:horizontal { 24 | background-color: black; 25 | margin: 0; 26 | } 27 | )")); 28 | this->setLayout(layout); 29 | connect(prog, &QProgressBar::valueChanged, this, &NDBProgressBar::setLabel); 30 | } 31 | 32 | /*! 33 | * \brief Destroy a progress bar 34 | */ 35 | NDBProgressBar::~NDBProgressBar() {} 36 | 37 | /*! 38 | * \brief Get the minimum value of a progress bar 39 | */ 40 | int NDBProgressBar::minimum() { 41 | return prog->minimum(); 42 | } 43 | 44 | /*! 45 | * \brief Set the minimum value of a progress bar 46 | * 47 | * Sets the minimum value of a progress bar to \a min 48 | */ 49 | void NDBProgressBar::setMinimum(int min) { 50 | prog->setMinimum(min); 51 | } 52 | 53 | /*! 54 | * \brief Get the maximum value of a progress bar 55 | */ 56 | int NDBProgressBar::maximum() { 57 | return prog->maximum(); 58 | } 59 | 60 | /*! 61 | * \brief Set the maximum value of a progress bar 62 | * 63 | * Sets the maximum value of a progress bar to \a max 64 | */ 65 | void NDBProgressBar::setMaximum(int max) { 66 | prog->setMaximum(max); 67 | } 68 | 69 | /*! 70 | * \brief Get the current value of a progress bar 71 | */ 72 | int NDBProgressBar::value() { 73 | return prog->value(); 74 | } 75 | 76 | /*! 77 | * \brief Set the current value of a progress bar 78 | * 79 | * Sets the current value of a progress bar to \a val 80 | */ 81 | void NDBProgressBar::setValue(int val) { 82 | prog->setValue(val); 83 | } 84 | 85 | /*! 86 | * \brief Set the label format of a progress bar 87 | * 88 | * Sets the format of the progress bar label to 89 | * \a format, which should use the same format 90 | * specification as a \l QProgressBar 91 | */ 92 | void NDBProgressBar::setFormat(QString const& format) { 93 | prog->setFormat(format); 94 | } 95 | 96 | /*! 97 | * \brief Get the text of a progress bar 98 | */ 99 | QString NDBProgressBar::text() { 100 | return prog->text(); 101 | } 102 | 103 | /*! 104 | * \brief Set the label of a progress bar 105 | * 106 | * Sets the label of a progress bar to the text value 107 | * of the underlying \l QProgressBar 108 | */ 109 | void NDBProgressBar::setLabel() { 110 | const QString t = prog->text(); 111 | label->setText(t); 112 | } 113 | 114 | } // namespace NDB 115 | -------------------------------------------------------------------------------- /src/ndb/NDBWidgets.h: -------------------------------------------------------------------------------- 1 | #ifndef NDB_WIDGETS_H 2 | #define NDB_WIDGETS_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | namespace NDB { 9 | 10 | class NDBProgressBar : public QWidget 11 | { 12 | Q_OBJECT 13 | public: 14 | NDBProgressBar(QWidget *parent = nullptr, Qt::WindowFlags f = Qt::WindowFlags()); 15 | ~NDBProgressBar(); 16 | int minimum(); 17 | void setMinimum(int min); 18 | int maximum(); 19 | void setMaximum(int max); 20 | int value(); 21 | void setValue(int val); 22 | void setFormat(QString const& format); 23 | QString text(); 24 | public Q_SLOTS: 25 | void setLabel(); 26 | private: 27 | QProgressBar* prog; 28 | QLabel* label; 29 | }; 30 | 31 | } // namespace NDB 32 | 33 | #endif // NDB_WIDGETS_H 34 | -------------------------------------------------------------------------------- /src/ndb/ndb.h: -------------------------------------------------------------------------------- 1 | #ifndef NDB_H 2 | #define NDB_H 3 | 4 | namespace NDB { 5 | enum Result{ 6 | Ok, 7 | NotImplemented, 8 | InitError, 9 | SymbolError, 10 | NullError, 11 | ForbiddenError, 12 | ParamError, 13 | ConnError 14 | }; 15 | 16 | } 17 | 18 | #endif // NDB_H -------------------------------------------------------------------------------- /src/ndb/nickeldbus.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | 6 | #include "NDBDbus.h" 7 | 8 | static const char ndb_ininstall_file[] = "/mnt/onboard/.adds/nickeldbus"; 9 | static const char ndb_version_str[] = NH_VERSION; 10 | 11 | NDB::NDBDbus *ndb; 12 | 13 | static int ndb_init() { 14 | // Ensure that the user visible version file has the correct 15 | // version number. 16 | if (FILE *f = fopen(ndb_ininstall_file, "w")) { 17 | nh_log("(init) Writing version to %s", ndb_ininstall_file); 18 | fwrite(ndb_version_str, sizeof(ndb_version_str) - 1, 1, f); 19 | fwrite("\n", sizeof(char), 1, f); 20 | fclose(f); 21 | } else { 22 | nh_log("(init) Failed to open %s with error %m", ndb_ininstall_file); 23 | } 24 | 25 | ndb = new NDB::NDBDbus(nullptr); 26 | if (!ndb->initSucceeded) { 27 | delete ndb; 28 | return -1; 29 | } 30 | ndb->connectSignals(); 31 | return 0; 32 | } 33 | 34 | static bool ndb_uninstall() { 35 | nh_delete_file("/usr/bin/qndb"); 36 | nh_delete_file("/etc/dbus-1/system.d/com-github-shermp-nickeldbus.conf"); 37 | nh_delete_file("/usr/local/nickeldbus/ndb_stylesheet.qss"); 38 | nh_delete_dir("/usr/local/nickeldbus"); 39 | return true; 40 | } 41 | 42 | static struct nh_info NickelDBusInfo = { 43 | .name = "NickelDBus", 44 | .desc = "Observe and control Nickel over D-Bus", 45 | .uninstall_flag = NULL, 46 | .uninstall_xflag = ndb_ininstall_file 47 | }; 48 | 49 | static struct nh_hook NickelDBusHook[] = { 50 | {0}, 51 | }; 52 | 53 | static struct nh_dlsym NickelDBusDlsym[] = { 54 | {0}, 55 | }; 56 | 57 | NickelHook( 58 | .init = ndb_init, 59 | .info = &NickelDBusInfo, 60 | .hook = NickelDBusHook, 61 | .dlsym = NickelDBusDlsym, 62 | .uninstall = ndb_uninstall, 63 | ) 64 | -------------------------------------------------------------------------------- /src/ndb/util.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "util.h" 4 | 5 | namespace NDB { 6 | 7 | void resolveSymbol(void* libnickel, const char *name, void **fn) { 8 | if (!(*fn = dlsym(libnickel, name))) { 9 | nh_log("info... could not load %s", name); 10 | } 11 | } 12 | 13 | void resolveSymbolRTLD(const char *name, void **fn) { 14 | if (!(*fn = dlsym(RTLD_DEFAULT, name))) { 15 | nh_log("info... could not load %s", name); 16 | } 17 | } 18 | 19 | } // namespace 20 | -------------------------------------------------------------------------------- /src/ndb/util.h: -------------------------------------------------------------------------------- 1 | #ifndef NDB_UTIL_H 2 | #define NDB_UTIL_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | namespace NDB { 9 | 10 | #ifndef NH_VERSION 11 | #define NH_VERSION "dev" 12 | #endif 13 | 14 | #define NDB_ASSERT(ret, cond, fmt, ...) if (!(cond)) { nh_log(fmt, ##__VA_ARGS__); return (ret); } 15 | #define NDB_ASSERT_RES(res, func) (res) = (func); if ((res) != Ok) { return (res); } 16 | 17 | // like NDB_ASSERT, but sends an appropriate d-bus error on the bus before returning 18 | // Note: make sure you are including and for this to work! 19 | #define NDB_DBUS_ASSERT(ret, dbus_err, cond, fmt, ...) if (!(cond)) { \ 20 | nh_log(fmt, ##__VA_ARGS__); \ 21 | if (calledFromDBus()) { \ 22 | QString qstr; \ 23 | sendErrorReply((dbus_err), qstr.sprintf(fmt, ##__VA_ARGS__)); \ 24 | } \ 25 | return (ret); \ 26 | } 27 | 28 | // Shorthand for the common USBMS assertion 29 | #define NDB_DBUS_USB_ASSERT(ret) NDB_DBUS_ASSERT(ret, QDBusError::InternalError, !ndbInUSBMS(), "not calling method %s: in usbms session", __func__) 30 | // Shorthand for the common nickel symbol resolve assertion 31 | #define NDB_DBUS_SYM_ASSERT(ret, cond) NDB_DBUS_ASSERT(ret, QDBusError::InternalError, cond, "%s: required symbol(s) not resolved", __func__) 32 | 33 | #define NDB_RESOLVE_SYMBOL(name, fn) resolveSymbol(libnickel, name, fn) 34 | 35 | #ifdef DEBUG 36 | #define NDB_DEBUG(fmt, ...) nh_log("[debug] %s:%d:%s() " fmt, __FILE__, __LINE__, __func__, ##__VA_ARGS__) 37 | #else 38 | #define NDB_DEBUG(fmt, ...) do {} while (0) 39 | #endif 40 | 41 | #define ARRAY_LEN(arr) (sizeof((arr)) / sizeof ((arr)[0])) 42 | 43 | void resolveSymbol(void* libnickel, const char *name, void **fn); 44 | void resolveSymbolRTLD(const char *name, void **fn); 45 | 46 | } // namespace NDB 47 | 48 | #endif // NDB_UTIL_H 49 | --------------------------------------------------------------------------------