Changeset View
Changeset View
Standalone View
Standalone View
applet/contents/ui/main.qml
Show All 17 Lines | 1 | /* | |||
---|---|---|---|---|---|
18 | along with this program. If not, see <http://www.gnu.org/licenses/>. | 18 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
19 | */ | 19 | */ | ||
20 | 20 | | |||
21 | import QtQuick 2.2 | 21 | import QtQuick 2.2 | ||
22 | import QtQuick.Layouts 1.0 | 22 | import QtQuick.Layouts 1.0 | ||
23 | 23 | | |||
24 | import org.kde.plasma.core 2.1 as PlasmaCore | 24 | import org.kde.plasma.core 2.1 as PlasmaCore | ||
25 | import org.kde.plasma.components 2.0 as PlasmaComponents | 25 | import org.kde.plasma.components 2.0 as PlasmaComponents | ||
26 | import org.kde.plasma.components 3.0 as PlasmaComponents3 | ||||
26 | import org.kde.plasma.extras 2.0 as PlasmaExtras | 27 | import org.kde.plasma.extras 2.0 as PlasmaExtras | ||
27 | import org.kde.plasma.plasmoid 2.0 | 28 | import org.kde.plasma.plasmoid 2.0 | ||
28 | 29 | | |||
29 | import org.kde.plasma.private.volume 0.1 | 30 | import org.kde.plasma.private.volume 0.1 | ||
30 | 31 | | |||
31 | import "../code/icon.js" as Icon | 32 | import "../code/icon.js" as Icon | ||
32 | 33 | | |||
33 | Item { | 34 | Item { | ||
34 | id: main | 35 | id: main | ||
35 | 36 | | |||
36 | property bool volumeFeedback: Plasmoid.configuration.volumeFeedback | 37 | property bool volumeFeedback: Plasmoid.configuration.volumeFeedback | ||
37 | property int maxVolumeValue: Math.round(Plasmoid.configuration.maximumVolume * PulseAudio.NormalVolume / 100.0) | 38 | property int maxVolumeValue: Math.round(Plasmoid.configuration.maximumVolume * PulseAudio.NormalVolume / 100.0) | ||
38 | property int volumeStep: Math.round(Plasmoid.configuration.volumeStep * PulseAudio.NormalVolume / 100.0) | 39 | property int volumeStep: Math.round(Plasmoid.configuration.volumeStep * PulseAudio.NormalVolume / 100.0) | ||
39 | property string displayName: i18n("Audio Volume") | 40 | property string displayName: i18n("Audio Volume") | ||
40 | property QtObject draggedStream: null | 41 | property QtObject draggedStream: null | ||
41 | 42 | | |||
42 | // DEFAULT_SINK_NAME in module-always-sink.c | 43 | // DEFAULT_SINK_NAME in module-always-sink.c | ||
43 | readonly property string dummyOutputName: "auto_null" | 44 | readonly property string dummyOutputName: "auto_null" | ||
44 | 45 | | |||
45 | Layout.minimumHeight: units.gridUnit * 18 | 46 | Layout.minimumHeight: units.gridUnit * 8 | ||
46 | Layout.minimumWidth: units.gridUnit * 18 | 47 | Layout.minimumWidth: units.gridUnit * 14 | ||
47 | Layout.preferredHeight: units.gridUnit * 20 | 48 | Layout.preferredHeight: units.gridUnit * 21 | ||
48 | Layout.preferredWidth: units.gridUnit * 20 | 49 | Layout.preferredWidth: units.gridUnit * 24 | ||
49 | 50 | Plasmoid.switchHeight: Layout.minimumHeight | |||
51 | Plasmoid.switchWidth: Layout.minimumWidth | ||||
50 | Plasmoid.icon: paSinkModel.preferredSink && !isDummyOutput(paSinkModel.preferredSink) ? Icon.name(paSinkModel.preferredSink.volume, paSinkModel.preferredSink.muted) | 52 | Plasmoid.icon: paSinkModel.preferredSink && !isDummyOutput(paSinkModel.preferredSink) ? Icon.name(paSinkModel.preferredSink.volume, paSinkModel.preferredSink.muted) | ||
51 | : Icon.name(0, true) | 53 | : Icon.name(0, true) | ||
52 | Plasmoid.switchWidth: units.gridUnit * 18 | | |||
53 | Plasmoid.switchHeight: units.gridUnit * 18 | | |||
54 | Plasmoid.toolTipMainText: { | 54 | Plasmoid.toolTipMainText: { | ||
55 | var sink = paSinkModel.preferredSink; | 55 | var sink = paSinkModel.preferredSink; | ||
56 | if (!sink || isDummyOutput(sink)) { | 56 | if (!sink || isDummyOutput(sink)) { | ||
57 | return displayName; | 57 | return displayName; | ||
58 | } | 58 | } | ||
59 | 59 | | |||
60 | if (sink.muted) { | 60 | if (sink.muted) { | ||
61 | return i18n("Audio Muted"); | 61 | return i18n("Audio Muted"); | ||
62 | } else { | 62 | } else { | ||
63 | return i18n("Volume at %1%", volumePercent(sink.volume)); | 63 | return i18n("Volume at %1%", volumePercent(sink.volume)); | ||
64 | } | 64 | } | ||
65 | } | 65 | } | ||
66 | Plasmoid.toolTipSubText: paSinkModel.preferredSink && !isDummyOutput(paSinkModel.preferredSink) ? paSinkModel.preferredSink.description : "" | 66 | Plasmoid.toolTipSubText: { | ||
67 | if (paSinkModel.preferredSink && !isDummyOutput(paSinkModel.preferredSink)) { | ||||
68 | var port = paSinkModel.preferredSink.ports[paSinkModel.preferredSink.activePortIndex]; | ||||
69 | if (port) { | ||||
70 | return port.description | ||||
71 | } | ||||
72 | return paSinkModel.preferredSink.name | ||||
73 | } | ||||
74 | return "" | ||||
75 | } | ||||
67 | 76 | | |||
68 | function isDummyOutput(output) { | 77 | function isDummyOutput(output) { | ||
69 | return output && output.name === dummyOutputName; | 78 | return output && output.name === dummyOutputName; | ||
70 | } | 79 | } | ||
71 | 80 | | |||
72 | function boundVolume(volume) { | 81 | function boundVolume(volume) { | ||
73 | return Math.max(PulseAudio.MinimalVolume, Math.min(volume, maxVolumeValue)); | 82 | return Math.max(PulseAudio.MinimalVolume, Math.min(volume, maxVolumeValue)); | ||
74 | } | 83 | } | ||
▲ Show 20 Lines • Show All 218 Lines • ▼ Show 20 Line(s) | |||||
293 | VolumeOSD { | 302 | VolumeOSD { | ||
294 | id: osd | 303 | id: osd | ||
295 | } | 304 | } | ||
296 | 305 | | |||
297 | VolumeFeedback { | 306 | VolumeFeedback { | ||
298 | id: feedback | 307 | id: feedback | ||
299 | } | 308 | } | ||
300 | 309 | | |||
310 | PlasmaCore.Svg { | ||||
311 | id: lineSvg | ||||
312 | imagePath: "widgets/line" | ||||
313 | } | ||||
314 | | ||||
301 | Plasmoid.fullRepresentation: ColumnLayout { | 315 | Plasmoid.fullRepresentation: ColumnLayout { | ||
302 | spacing: units.smallSpacing | 316 | spacing: units.smallSpacing | ||
ngraham: Revert this change | |||||
303 | Layout.minimumHeight: main.Layout.minimumHeight | 317 | Layout.preferredHeight: main.Layout.preferredHeight | ||
304 | Layout.minimumWidth: main.Layout.minimumWidth | 318 | Layout.preferredWidth: main.Layout.preferredWidth | ||
305 | 319 | | |||
306 | function beginMoveStream(type, stream) { | 320 | function beginMoveStream(type, stream) { | ||
307 | if (type == "sink") { | 321 | if (type == "sink") { | ||
308 | sourceView.visible = false; | 322 | sourceView.visible = false; | ||
309 | sourceViewHeader.visible = false; | | |||
310 | } else if (type == "source") { | 323 | } else if (type == "source") { | ||
311 | sinkView.visible = false; | 324 | sinkView.visible = false; | ||
312 | sinkViewHeader.visible = false; | | |||
313 | } | 325 | } | ||
314 | 326 | | |||
327 | devicesLine.visible = false; | ||||
315 | tabBar.currentTab = devicesTab; | 328 | tabBar.currentTab = devicesTab; | ||
316 | } | 329 | } | ||
317 | 330 | | |||
318 | function endMoveStream() { | 331 | function endMoveStream() { | ||
319 | tabBar.currentTab = streamsTab; | 332 | tabBar.currentTab = streamsTab; | ||
320 | 333 | | |||
321 | sourceView.visible = true; | 334 | sourceView.visible = true; | ||
322 | sourceViewHeader.visible = true; | 335 | devicesLine.visible = true; | ||
323 | sinkView.visible = true; | 336 | sinkView.visible = true; | ||
324 | sinkViewHeader.visible = true; | | |||
325 | } | 337 | } | ||
326 | 338 | | |||
327 | RowLayout { | 339 | RowLayout { | ||
328 | spacing: units.smallSpacing | 340 | spacing: units.smallSpacing | ||
329 | Layout.fillWidth: true | 341 | Layout.fillWidth: true | ||
330 | 342 | | |||
331 | PlasmaComponents.TabBar { | 343 | PlasmaComponents.TabBar { | ||
332 | id: tabBar | 344 | id: tabBar | ||
333 | Layout.fillWidth: true | 345 | Layout.fillWidth: true | ||
334 | activeFocusOnTab: true | 346 | activeFocusOnTab: true | ||
335 | 347 | | |||
336 | PlasmaComponents.TabButton { | 348 | PlasmaComponents.TabButton { | ||
337 | id: devicesTab | 349 | id: devicesTab | ||
338 | text: i18n("Devices") | 350 | text: i18n("Devices") | ||
339 | } | 351 | } | ||
340 | 352 | | |||
341 | PlasmaComponents.TabButton { | 353 | PlasmaComponents.TabButton { | ||
342 | id: streamsTab | 354 | id: streamsTab | ||
343 | text: i18n("Applications") | 355 | text: i18n("Applications") | ||
344 | } | 356 | } | ||
345 | } | 357 | } | ||
346 | | ||||
347 | PlasmaComponents.ToolButton { | | |||
348 | Layout.alignment: Qt.AlignBottom | | |||
349 | tooltip: plasmoid.action("configure").text | | |||
350 | iconName: "configure" | | |||
351 | Accessible.name: tooltip | | |||
352 | onClicked: { | | |||
353 | plasmoid.action("configure").trigger(); | | |||
354 | } | | |||
355 | } | | |||
356 | } | 358 | } | ||
357 | 359 | | |||
358 | PlasmaExtras.ScrollArea { | 360 | PlasmaExtras.ScrollArea { | ||
359 | id: scrollView; | 361 | id: scrollView; | ||
360 | 362 | | |||
361 | Layout.fillWidth: true | 363 | Layout.fillWidth: true | ||
362 | Layout.fillHeight: true | 364 | Layout.fillHeight: true | ||
363 | 365 | | |||
364 | horizontalScrollBarPolicy: Qt.ScrollBarAlwaysOff | 366 | horizontalScrollBarPolicy: Qt.ScrollBarAlwaysOff | ||
365 | flickableItem.boundsBehavior: Flickable.StopAtBounds; | 367 | flickableItem.boundsBehavior: Flickable.StopAtBounds; | ||
366 | 368 | | |||
367 | //our scroll isn't a list of delegates, all internal items are tab focussable, making this redundant | 369 | //our scroll isn't a list of delegates, all internal items are tab focussable, making this redundant | ||
368 | activeFocusOnTab: false | 370 | activeFocusOnTab: false | ||
369 | 371 | | |||
370 | Item { | 372 | Item { | ||
371 | width: streamsView.visible ? streamsView.width : devicesView.width | 373 | width: streamsView.visible ? streamsView.width : devicesView.width | ||
372 | height: streamsView.visible ? streamsView.height : devicesView.height | 374 | height: streamsView.visible ? streamsView.height : devicesView.height | ||
373 | 375 | | |||
374 | ColumnLayout { | 376 | ColumnLayout { | ||
375 | id: streamsView | 377 | id: streamsView | ||
378 | spacing: 0 | ||||
376 | visible: tabBar.currentTab == streamsTab | 379 | visible: tabBar.currentTab == streamsTab | ||
377 | readonly property bool simpleMode: (sinkInputView.count >= 1 && sourceOutputView.count == 0) || (sinkInputView.count == 0 && sourceOutputView.count >= 1) | 380 | readonly property bool simpleMode: (sinkInputView.count >= 1 && sourceOutputView.count == 0) || (sinkInputView.count == 0 && sourceOutputView.count >= 1) | ||
378 | property int maximumWidth: scrollView.viewport.width | 381 | property int maximumWidth: scrollView.viewport.width | ||
379 | width: maximumWidth | 382 | width: maximumWidth | ||
380 | Layout.maximumWidth: maximumWidth | 383 | Layout.maximumWidth: maximumWidth | ||
381 | 384 | | |||
382 | Header { | | |||
383 | Layout.fillWidth: true | | |||
384 | visible: sinkInputView.count > 0 && !streamsView.simpleMode | | |||
385 | text: i18n("Playback Streams") | | |||
386 | } | | |||
387 | ListView { | 385 | ListView { | ||
388 | id: sinkInputView | 386 | id: sinkInputView | ||
389 | 387 | | |||
390 | Layout.fillWidth: true | 388 | Layout.fillWidth: true | ||
391 | Layout.minimumHeight: contentHeight | 389 | Layout.minimumHeight: contentHeight | ||
392 | Layout.maximumHeight: contentHeight | 390 | Layout.maximumHeight: contentHeight | ||
393 | 391 | | |||
394 | model: PulseObjectFilterModel { | 392 | model: PulseObjectFilterModel { | ||
395 | filters: [ { role: "VirtualStream", value: false } ] | 393 | filters: [ { role: "VirtualStream", value: false } ] | ||
396 | sourceModel: SinkInputModel {} | 394 | sourceModel: SinkInputModel {} | ||
397 | } | 395 | } | ||
398 | boundsBehavior: Flickable.StopAtBounds; | 396 | boundsBehavior: Flickable.StopAtBounds; | ||
399 | delegate: StreamListItem { | 397 | delegate: StreamListItem { | ||
400 | type: "sink-input" | 398 | type: "sink-input" | ||
401 | draggable: sinkView.count > 1 | 399 | draggable: sinkView.count > 1 | ||
402 | onlyOne: streamsView.simpleMode | | |||
403 | } | 400 | } | ||
404 | } | 401 | } | ||
405 | 402 | | |||
406 | Header { | 403 | PlasmaCore.SvgItem { | ||
ngraham: I think there isn't a line here in the mockup, right? | |||||
407 | Layout.fillWidth: true | 404 | elementId: "horizontal-line" | ||
408 | visible: sourceOutputView.count > 0 && !streamsView.simpleMode | 405 | Layout.preferredWidth: scrollView.viewport.width - units.smallSpacing * 4 | ||
409 | text: i18n("Recording Streams") | 406 | Layout.preferredHeight: naturalSize.height | ||
407 | Layout.leftMargin: units.smallSpacing * 2 | ||||
408 | Layout.rightMargin: units.smallSpacing * 2 | ||||
409 | Layout.topMargin: units.smallSpacing | ||||
410 | svg: lineSvg | ||||
411 | visible: sinkInputView.model.count > 0 && sourceOutputView.model.count > 0 | ||||
This is the line that separates the playback and recording applications. gvgeo: This is the line that separates the playback and recording applications.
Just notice that… | |||||
410 | } | 412 | } | ||
413 | | ||||
411 | ListView { | 414 | ListView { | ||
412 | id: sourceOutputView | 415 | id: sourceOutputView | ||
413 | 416 | | |||
414 | Layout.fillWidth: true | 417 | Layout.fillWidth: true | ||
415 | Layout.minimumHeight: contentHeight | 418 | Layout.minimumHeight: contentHeight | ||
416 | Layout.maximumHeight: contentHeight | 419 | Layout.maximumHeight: contentHeight | ||
417 | 420 | | |||
418 | model: PulseObjectFilterModel { | 421 | model: PulseObjectFilterModel { | ||
419 | filters: [ { role: "VirtualStream", value: false } ] | 422 | filters: [ { role: "VirtualStream", value: false } ] | ||
420 | sourceModel: SourceOutputModel {} | 423 | sourceModel: SourceOutputModel {} | ||
421 | } | 424 | } | ||
422 | boundsBehavior: Flickable.StopAtBounds; | 425 | boundsBehavior: Flickable.StopAtBounds; | ||
423 | delegate: StreamListItem { | 426 | delegate: StreamListItem { | ||
424 | type: "source-input" | 427 | type: "source-input" | ||
425 | draggable: sourceView.count > 1 | 428 | draggable: sourceView.count > 1 | ||
426 | onlyOne: streamsView.simpleMode | | |||
427 | } | 429 | } | ||
428 | } | 430 | } | ||
429 | } | 431 | } | ||
430 | 432 | | |||
431 | ColumnLayout { | 433 | ColumnLayout { | ||
432 | id: devicesView | 434 | id: devicesView | ||
433 | visible: tabBar.currentTab == devicesTab | 435 | visible: tabBar.currentTab == devicesTab | ||
434 | readonly property bool simpleMode: sinkView.count == 1 && sourceView.count == 1 | 436 | readonly property bool simpleMode: sinkView.count == 1 && sourceView.count == 1 | ||
435 | property int maximumWidth: scrollView.viewport.width | 437 | property int maximumWidth: scrollView.viewport.width | ||
436 | width: maximumWidth | 438 | width: maximumWidth | ||
437 | Layout.maximumWidth: maximumWidth | 439 | Layout.maximumWidth: maximumWidth | ||
440 | spacing: 0 | ||||
438 | 441 | | |||
439 | Header { | | |||
440 | id: sinkViewHeader | | |||
441 | Layout.fillWidth: true | | |||
442 | visible: sinkView.count > 0 && !devicesView.simpleMode | | |||
443 | text: i18n("Playback Devices") | | |||
444 | } | | |||
445 | ListView { | 442 | ListView { | ||
446 | id: sinkView | 443 | id: sinkView | ||
447 | 444 | | |||
448 | Layout.fillWidth: true | 445 | Layout.fillWidth: true | ||
449 | Layout.minimumHeight: contentHeight | 446 | Layout.minimumHeight: contentHeight | ||
450 | Layout.maximumHeight: contentHeight | 447 | Layout.maximumHeight: contentHeight | ||
448 | spacing: 0 | ||||
451 | 449 | | |||
452 | model: PlasmaCore.SortFilterModel { | 450 | model: PlasmaCore.SortFilterModel { | ||
453 | sortRole: "SortByDefault" | 451 | sortRole: "SortByDefault" | ||
454 | sortOrder: Qt.DescendingOrder | 452 | sortOrder: Qt.DescendingOrder | ||
455 | sourceModel: paSinkModel | 453 | sourceModel: paSinkModel | ||
456 | 454 | | |||
457 | filterCallback: function (source_row, value) { | 455 | filterCallback: function (source_row, value) { | ||
458 | var idx = sourceModel.index(source_row, 0); | 456 | var idx = sourceModel.index(source_row, 0); | ||
459 | 457 | | |||
460 | if (sourceModel.data(idx, sourceModel.role("Name")) === dummyOutputName) { | 458 | if (sourceModel.data(idx, sourceModel.role("Name")) === dummyOutputName) { | ||
461 | return false; | 459 | return false; | ||
462 | } | 460 | } | ||
463 | 461 | | |||
464 | return true; | 462 | return true; | ||
465 | } | 463 | } | ||
466 | } | 464 | } | ||
467 | boundsBehavior: Flickable.StopAtBounds; | 465 | boundsBehavior: Flickable.StopAtBounds; | ||
468 | delegate: DeviceListItem { | 466 | delegate: DeviceListItem { | ||
469 | type: "sink" | 467 | type: "sink" | ||
470 | onlyOne: devicesView.simpleMode | | |||
471 | } | 468 | } | ||
472 | } | 469 | } | ||
473 | 470 | | |||
474 | Header { | 471 | PlasmaCore.SvgItem { | ||
ngraham: ditto | |||||
475 | id: sourceViewHeader | 472 | id: devicesLine | ||
476 | Layout.fillWidth: true | 473 | elementId: "horizontal-line" | ||
477 | visible: sourceView.count > 0 && !devicesView.simpleMode | 474 | Layout.preferredWidth: scrollView.viewport.width - units.smallSpacing * 4 | ||
478 | text: i18n("Recording Devices") | 475 | Layout.leftMargin: units.smallSpacing * 2 | ||
476 | Layout.rightMargin: Layout.leftMargin | ||||
477 | Layout.topMargin: units.smallSpacing | ||||
478 | svg: lineSvg | ||||
479 | visible: sinkView.model.count > 0 && sourceView.model.count > 0 && (sinkView.model.count > 1 || sourceView.model.count > 1) | ||||
479 | } | 480 | } | ||
481 | | ||||
480 | ListView { | 482 | ListView { | ||
481 | id: sourceView | 483 | id: sourceView | ||
482 | 484 | | |||
483 | Layout.fillWidth: true | 485 | Layout.fillWidth: true | ||
484 | Layout.minimumHeight: contentHeight | 486 | Layout.minimumHeight: contentHeight | ||
485 | Layout.maximumHeight: contentHeight | 487 | Layout.maximumHeight: contentHeight | ||
486 | 488 | | |||
487 | model: PulseObjectFilterModel { | 489 | model: PulseObjectFilterModel { | ||
488 | sortRole: "SortByDefault" | 490 | sortRole: "SortByDefault" | ||
489 | sortOrder: Qt.DescendingOrder | 491 | sortOrder: Qt.DescendingOrder | ||
490 | sourceModel: paSourceModel | 492 | sourceModel: paSourceModel | ||
491 | } | 493 | } | ||
492 | boundsBehavior: Flickable.StopAtBounds; | 494 | boundsBehavior: Flickable.StopAtBounds; | ||
493 | delegate: DeviceListItem { | 495 | delegate: DeviceListItem { | ||
494 | type: "source" | 496 | type: "source" | ||
495 | onlyOne: devicesView.simpleMode | | |||
496 | } | 497 | } | ||
497 | } | 498 | } | ||
498 | } | 499 | } | ||
499 | 500 | | |||
500 | PlasmaExtras.Heading { | 501 | PlasmaExtras.Heading { | ||
501 | level: 4 | 502 | level: 4 | ||
502 | opacity: 0.8 | 503 | opacity: 0.8 | ||
503 | width: parent.width | 504 | width: parent.width | ||
Show All 13 Lines | 513 | PlasmaExtras.Heading { | |||
517 | visible: devicesView.visible && !sinkView.count && !sourceView.count | 518 | visible: devicesView.visible && !sinkView.count && !sourceView.count | ||
518 | text: i18n("No output or input devices found") | 519 | text: i18n("No output or input devices found") | ||
519 | wrapMode: Text.WordWrap | 520 | wrapMode: Text.WordWrap | ||
520 | verticalAlignment: Text.AlignVCenter | 521 | verticalAlignment: Text.AlignVCenter | ||
521 | horizontalAlignment: Text.AlignHCenter | 522 | horizontalAlignment: Text.AlignHCenter | ||
522 | } | 523 | } | ||
523 | } | 524 | } | ||
524 | } | 525 | } | ||
526 | | ||||
527 | PlasmaCore.SvgItem { | ||||
you can give it negative side margins to get it to touch the sides of the pop-up, as in the mockup ngraham: you can give it negative side margins to get it to touch the sides of the pop-up, as in the… | |||||
528 | elementId: "horizontal-line" | ||||
529 | Layout.fillWidth: true | ||||
530 | Layout.topMargin: 0 - units.smallSpacing / 2 | ||||
531 | Layout.leftMargin: 0 - units.smallSpacing * 1.5 | ||||
532 | Layout.rightMargin: Layout.leftMargin | ||||
533 | svg: lineSvg | ||||
534 | } | ||||
535 | | ||||
536 | RowLayout { | ||||
537 | | ||||
538 | Item { | ||||
539 | Layout.fillWidth: true | ||||
540 | } | ||||
541 | | ||||
So this doesn't actually do anything yet? Obviously that needs to change before this can land. :) Also the checked state needs to be saved somewhere. ngraham: So this doesn't actually do anything yet? Obviously that needs to change before this can land. | |||||
542 | PlasmaComponents.ToolButton { | ||||
543 | tooltip: plasmoid.action("configure").text | ||||
544 | iconName: "configure" | ||||
ngraham: Don't use a separate Heading here; give the Checkbox a `text:` property | |||||
545 | Accessible.name: tooltip | ||||
546 | onClicked: plasmoid.action("configure").trigger() | ||||
547 | } | ||||
548 | } | ||||
525 | } | 549 | } | ||
526 | 550 | | |||
527 | Component.onCompleted: { | 551 | Component.onCompleted: { | ||
528 | MicrophoneIndicator.init(); | 552 | MicrophoneIndicator.init(); | ||
529 | } | 553 | } | ||
530 | } | 554 | } |
Revert this change