diff -Nru albert-0.9.4/data/deprecated_themes/Android.qss albert-0.10.1/data/deprecated_themes/Android.qss --- albert-0.9.4/data/deprecated_themes/Android.qss 2017-03-01 10:22:31.000000000 +0000 +++ albert-0.10.1/data/deprecated_themes/Android.qss 1970-01-01 00:00:00.000000000 +0000 @@ -1,95 +0,0 @@ -/* - * author: Manuel Schneider - * - * Check http://doc.qt.io/qt-5/stylesheet-syntax.html especially the subtopics: - * The Style Sheet Syntax (http://doc.qt.io/qt-5/stylesheet-syntax.html) - * Qt Style Sheets Reference (http://doc.qt.io/qt-5/stylesheet-reference.html) - */ - -#bottomFrame { - width:640px; - min-width:640px; - max-width:640px; - padding: 7px; - border-radius: 14px; - background-color: rgba(154, 205, 0, 128); -} - -#topFrame { - background-color: #f9f9f9; - padding: 7px; - border-radius: 7px; -} - -#inputLine { - padding: 2px; - border-radius: 2px; - font: 36px "Ubuntu"; - border: none; - color : #f9f9f9; - background-color: #9acd00; - selection-color: #9acd00; - selection-background-color: #f9f9f9; -} - -#settingsButton { - min-width:14px; - min-height:14px; - max-width:14px; - max-height:14px; - border: none; - border-radius: 2px; - color: #f9f9f9; - background-color: transparent; -} - -#settingsButton:hover { - background-color: #9acd00; -} - -/********** proposalList **********/ - -#proposalList { - icon-size:48px; - font: 26px "Ubuntu"; - border-radius: 5px; - color: #6d6e71; - background-color: transparent; -} - -#proposalList::item{ - height:48px; - border-radius: 5px; - border: 1px solid transparent; -} - -#proposalList::item:selected{ - border: 1px solid #9acd00; - background: qlineargradient(x1:1, y1:1, x2:0, y2:0, stop:0.0 rgba(154, 205, 0, 32), stop:0.5 rgba(0,0,0,0), stop:1.0 rgba(154, 205, 0,32)); -} - -#proposalList::item:hover{} -#proposalList::item:selected:!active{} -#proposalList::item:selected:active{} -#proposalList::item:alternate{} - -/********** SCROLLBAR **********/ - -#proposalList QScrollBar:vertical { - width: 5px; - background: transparent; -} - -#proposalList QScrollBar::handle:vertical { - background: #9acd00; - min-height: 24px; -} - -#proposalList QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical, -#proposalList QScrollBar::up-arrow:vertical, QScrollBar::down-arrow:vertical, -#proposalList QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical { - border: 0px; - width: 0px; - height: 0px; - background: transparent; -} diff -Nru albert-0.9.4/data/deprecated_themes/Arc Blue.qss albert-0.10.1/data/deprecated_themes/Arc Blue.qss --- albert-0.9.4/data/deprecated_themes/Arc Blue.qss 2017-03-01 10:22:31.000000000 +0000 +++ albert-0.10.1/data/deprecated_themes/Arc Blue.qss 1970-01-01 00:00:00.000000000 +0000 @@ -1,101 +0,0 @@ -/* - * author: - * - * Check http://doc.qt.io/qt-5/stylesheet-syntax.html especially the subtopics: - * The Style Sheet Syntax (http://doc.qt.io/qt-5/stylesheet-syntax.html) - * Qt Style Sheets Reference (http://doc.qt.io/qt-5/stylesheet-reference.html) - */ - -#bottomFrame * { - color : #aaa; - background-color: #000000; - selection-color: #3a3a3a; - selection-background-color: #aaa; -} - -#bottomFrame { - width:640px; - min-width:640px; - max-width:640px; - padding: 3px; - border-radius: 3px; - background-color: #E7E8EB; -} - -#topFrame { - padding: 1px; - border-radius: 3px; - background-color: #CFD6E6; -} - -#inputLine { - padding: 2px; - border-radius: 3px; - font: 36px "Ubuntu"; - border: none; - color: #727A8F; - background-color: #FDFDFD; -} - -#settingsButton { - min-width:14px; - min-height:14px; - max-width:14px; - max-height:14px; - border: none; - border-radius: 7px; - color : #eee; - background-color: transparent; -} - -#settingsButton:hover { - background-color: #282828; -} - -/********** proposalList **********/ - -#proposalList { - icon-size:48px; - font: 26px "Ubuntu"; - border-radius: 3px; - background-color: #FDFDFD; - color: #5C6175; -} - -#proposalList::item{ - height:48px; - border-radius: 1px; - border: 0px solid #404552; -} - -#proposalList::item:selected{ - border: 0px solid #CFD6E6; - background: #95C4FB; - color: #FFFFFF; -} - -#proposalList::item:hover{} -#proposalList::item:selected:!active{} -#proposalList::item:selected:active{} -#proposalList::item:alternate{} - -/********** SCROLLBAR **********/ - -#proposalList QScrollBar:vertical { - width: 5px; - background: #FCFCFC; -} - -#proposalList QScrollBar::handle:vertical { - background: #B8BABF; - min-height: 24px; -} - -#proposalList QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical, -#proposalList QScrollBar::up-arrow:vertical, QScrollBar::down-arrow:vertical, -#proposalList QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical { - border: 0px; - width: 0px; - height: 0px; - background: transparent; -} diff -Nru albert-0.9.4/data/deprecated_themes/Arc Dark Blue.qss albert-0.10.1/data/deprecated_themes/Arc Dark Blue.qss --- albert-0.9.4/data/deprecated_themes/Arc Dark Blue.qss 2017-03-01 10:22:31.000000000 +0000 +++ albert-0.10.1/data/deprecated_themes/Arc Dark Blue.qss 1970-01-01 00:00:00.000000000 +0000 @@ -1,100 +0,0 @@ -/* - * author: - * - * Check http://doc.qt.io/qt-5/stylesheet-syntax.html especially the subtopics: - * The Style Sheet Syntax (http://doc.qt.io/qt-5/stylesheet-syntax.html) - * Qt Style Sheets Reference (http://doc.qt.io/qt-5/stylesheet-reference.html) - */ - -#bottomFrame * { - color : #aaa; - background-color: #000000; - selection-color: #3a3a3a; - selection-background-color: #aaa; -} - -#bottomFrame { - width:640px; - min-width:640px; - max-width:640px; - padding: 3px; - border-radius: 3px; - background-color: #383C4A; -} - -#topFrame { - padding: 1px; - border-radius: 3px; - background-color: #21252B; -} - -#inputLine { - padding: 2px; - border-radius: 3px; - font: 36px "Ubuntu"; - border: none; - color: #CDD3DC; - background-color: #404552; -} - -#settingsButton { - min-width:14px; - min-height:14px; - max-width:14px; - max-height:14px; - border: none; - border-radius: 7px; - color : #444; - background-color: transparent; -} - -#settingsButton:hover { - background-color: #282828; -} - -/********** proposalList **********/ - -#proposalList { - icon-size:48px; - font: 26px "Ubuntu"; - border-radius: 3px; - background-color: #383C4A; - color: #CDD3DC; -} - -#proposalList::item{ - height:48px; - border-radius: 1px; - border: 0px solid transparent; -} - -#proposalList::item:selected{ - border: 0px solid #888; - background: #4084D6; -} - -#proposalList::item:hover{} -#proposalList::item:selected:!active{} -#proposalList::item:selected:active{} -#proposalList::item:alternate{} - -/********** SCROLLBAR **********/ - -#proposalList QScrollBar:vertical { - width: 5px; - background: #404552; -} - -#proposalList QScrollBar::handle:vertical { - background: #676B78; - min-height: 24px; -} - -#proposalList QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical, -#proposalList QScrollBar::up-arrow:vertical, QScrollBar::down-arrow:vertical, -#proposalList QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical { - border: 0px; - width: 0px; - height: 0px; - background: transparent; -} diff -Nru albert-0.9.4/data/deprecated_themes/Arc Dark Grey.qss albert-0.10.1/data/deprecated_themes/Arc Dark Grey.qss --- albert-0.9.4/data/deprecated_themes/Arc Dark Grey.qss 2017-03-01 10:22:31.000000000 +0000 +++ albert-0.10.1/data/deprecated_themes/Arc Dark Grey.qss 1970-01-01 00:00:00.000000000 +0000 @@ -1,100 +0,0 @@ -/* - * author: - * - * Check http://doc.qt.io/qt-5/stylesheet-syntax.html especially the subtopics: - * The Style Sheet Syntax (http://doc.qt.io/qt-5/stylesheet-syntax.html) - * Qt Style Sheets Reference (http://doc.qt.io/qt-5/stylesheet-reference.html) - */ - -#bottomFrame * { - color : #aaa; - background-color: #000000; - selection-color: #3a3a3a; - selection-background-color: #aaa; -} - -#bottomFrame { - width:640px; - min-width:640px; - max-width:640px; - padding: 3px; - border-radius: 3px; - background-color: #383C4A; -} - -#topFrame { - padding: 1px; - border-radius: 3px; - background-color: #21252B; -} - -#inputLine { - padding: 2px; - border-radius: 3px; - font: 36px "Ubuntu"; - border: none; - color: #CDD3DC; - background-color: #404552; -} - -#settingsButton { - min-width:14px; - min-height:14px; - max-width:14px; - max-height:14px; - border: none; - border-radius: 7px; - color : #444; - background-color: transparent; -} - -#settingsButton:hover { - background-color: #282828; -} - -/********** proposalList **********/ - -#proposalList { - icon-size:48px; - font: 26px "Ubuntu"; - border-radius: 3px; - background-color: #383C4A; - color: #CDD3DC; -} - -#proposalList::item{ - height:48px; - border-radius: 1px; - border: 0px solid #404552; -} - -#proposalList::item:selected{ - border: 1px solid #2B2E39; - background: #404552; -} - -#proposalList::item:hover{} -#proposalList::item:selected:!active{} -#proposalList::item:selected:active{} -#proposalList::item:alternate{} - -/********** SCROLLBAR **********/ - -#proposalList QScrollBar:vertical { - width: 5px; - background: #404552; -} - -#proposalList QScrollBar::handle:vertical { - background: #676B78; - min-height: 24px; -} - -#proposalList QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical, -#proposalList QScrollBar::up-arrow:vertical, QScrollBar::down-arrow:vertical, -#proposalList QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical { - border: 0px; - width: 0px; - height: 0px; - background: transparent; -} diff -Nru albert-0.9.4/data/deprecated_themes/Arc Grey.qss albert-0.10.1/data/deprecated_themes/Arc Grey.qss --- albert-0.9.4/data/deprecated_themes/Arc Grey.qss 2017-03-01 10:22:31.000000000 +0000 +++ albert-0.10.1/data/deprecated_themes/Arc Grey.qss 1970-01-01 00:00:00.000000000 +0000 @@ -1,101 +0,0 @@ -/* - * author: - * - * Check http://doc.qt.io/qt-5/stylesheet-syntax.html especially the subtopics: - * The Style Sheet Syntax (http://doc.qt.io/qt-5/stylesheet-syntax.html) - * Qt Style Sheets Reference (http://doc.qt.io/qt-5/stylesheet-reference.html) - */ - -#bottomFrame * { - color : #aaa; - background-color: #000000; - selection-color: #3a3a3a; - selection-background-color: #aaa; -} - -#bottomFrame { - width:640px; - min-width:640px; - max-width:640px; - padding: 3px; - border-radius: 3px; - background-color: #E7E8EB; -} - -#topFrame { - padding: 1px; - border-radius: 3px; - background-color: #CFD6E6; -} - -#inputLine { - padding: 2px; - border-radius: 3px; - font: 36px "Ubuntu"; - border: none; - color: #727A8F; - background-color: #FDFDFD; -} - -#settingsButton { - min-width:14px; - min-height:14px; - max-width:14px; - max-height:14px; - border: none; - border-radius: 7px; - color : #eee; - background-color: transparent; -} - -#settingsButton:hover { - background-color: #282828; -} - -/********** proposalList **********/ - -#proposalList { - icon-size:48px; - font: 26px "Ubuntu"; - border-radius: 3px; - background-color: #FDFDFD; - color: #5C6175; -} - -#proposalList::item{ - height:48px; - border-radius: 1px; - border: 0px solid #404552; -} - -#proposalList::item:selected{ - border: 1px solid #4084D6; - background: #F5F6F7; - color: #FFFFFF; -} - -#proposalList::item:hover{} -#proposalList::item:selected:!active{} -#proposalList::item:selected:active{} -#proposalList::item:alternate{} - -/********** SCROLLBAR **********/ - -#proposalList QScrollBar:vertical { - width: 5px; - background: #FCFCFC; -} - -#proposalList QScrollBar::handle:vertical { - background: #B8BABF; - min-height: 24px; -} - -#proposalList QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical, -#proposalList QScrollBar::up-arrow:vertical, QScrollBar::down-arrow:vertical, -#proposalList QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical { - border: 0px; - width: 0px; - height: 0px; - background: transparent; -} diff -Nru albert-0.9.4/data/deprecated_themes/Pinboard.qss albert-0.10.1/data/deprecated_themes/Pinboard.qss --- albert-0.9.4/data/deprecated_themes/Pinboard.qss 2017-03-01 10:22:31.000000000 +0000 +++ albert-0.10.1/data/deprecated_themes/Pinboard.qss 1970-01-01 00:00:00.000000000 +0000 @@ -1,95 +0,0 @@ -/* - * author: Manuel Schneider - * - * Check http://doc.qt.io/qt-5/stylesheet-syntax.html especially the subtopics: - * The Style Sheet Syntax (http://doc.qt.io/qt-5/stylesheet-syntax.html) - * Qt Style Sheets Reference (http://doc.qt.io/qt-5/stylesheet-reference.html) - */ - -#bottomFrame * { - color : #655332; - background-color: #f8edda; - selection-color: #f8edda; - selection-background-color: #655332; -} - -#bottomFrame { - width:640px; - min-width:640px; - max-width:640px; - padding: 7px; - border-radius: 14px; - background-color: rgba(248, 237, 218, 64); -} - -#topFrame { - padding: 7px; - border-radius: 7px; -} - -#inputLine { - padding: 2px; - border-radius: 2px; - font: 36px "Ubuntu"; - border: none; - background-color: #f4e3c8; -} - -#settingsButton { - min-width:14px; - min-height:14px; - max-width:14px; - max-height:14px; - border: none; - border-radius: 2px; - background-color: transparent; -} - -#settingsButton:hover { - background-color: #f8edda; -} - -/********** proposalList **********/ - -#proposalList { - icon-size:48px; - font: 26px "Ubuntu"; - border-radius: 5px; - background-color: transparent; -} - -#proposalList::item{ - height:48px; - border-radius: 5px; - border: 1px solid transparent; -} - -#proposalList::item:selected{ - border: 1px solid #e5cba3; -} - -#proposalList::item:hover{} -#proposalList::item:selected:!active{} -#proposalList::item:selected:active{} -#proposalList::item:alternate{} - -/********** SCROLLBAR **********/ - -#proposalList QScrollBar:vertical { - width: 5px; - background: transparent; -} - -#proposalList QScrollBar::handle:vertical { - background: #655332; - min-height: 24px; -} - -#proposalList QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical, -#proposalList QScrollBar::up-arrow:vertical, QScrollBar::down-arrow:vertical, -#proposalList QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical { - border: 0px; - width: 0px; - height: 0px; - background: transparent; -} diff -Nru albert-0.9.4/data/SlickTemplate.qss albert-0.10.1/data/SlickTemplate.qss --- albert-0.9.4/data/SlickTemplate.qss 2017-03-01 10:22:31.000000000 +0000 +++ albert-0.10.1/data/SlickTemplate.qss 2017-03-20 15:24:06.000000000 +0000 @@ -7,85 +7,81 @@ */ * { - border: none; - font-family:"DejaVu Sans"; - font-weight: 200; - color : #%foreground_color%; - background-color: #%background_color%; + border: none; + color : #%foreground_color%; + background-color: #%background_color%; } #frame { - padding: 12px; - border-radius: 5px; - background-color: #%background_color%; - border: 1px solid #20808080; - - /* Workaround for Qt to get fixed size button*/ - min-width:640px; - max-width:640px; + padding: 6px 0px; + border-radius: 8px; + background-color: #%background_color%; + min-width:640px; + max-width:640px; } #inputLine { - font-size: 36px; - selection-color: #%background_color%; - selection-background-color: #%foreground_color%; - background-color: transparent; + padding: 0px 8px; + font-size: 36px; + selection-color: #%background_color%; + selection-background-color: #%foreground_color%; + background-color: transparent; } #settingsButton { - color: #%button_color%; - background-color: transparent; - padding: 8px; - - /* Workaround for Qt to get fixed size button*/ - min-width:14px; - min-height:14px; - max-width:14px; - max-height:14px; + margin: 6px 6px 0px 0px; + color: #%button_color%; + background-color: transparent; + padding: 2px; + min-width:14px; + min-height:14px; + max-width:14px; + max-height:14px; } /********** ListViews ************/ +QListView { + background: transparent; +} + QListView::item:selected { - background: #%selection_background_color%; + background: #%selection_background_color%; } QListView QScrollBar:vertical { - width: 2px; - background: transparent; + width: 3px; + background: transparent; } QListView QScrollBar::handle:vertical { - background: #%scroll_color%; - min-height: 24px; -} - -QListView ScrollBar::add-line:vertical, QScrollBar::sub-line:vertical, -QListView ScrollBar::up-arrow:vertical, QScrollBar::down-arrow:vertical, -QListView ScrollBar::add-page:vertical, QScrollBar::sub-page:vertical { - border: 0px; - width: 0px; - height: 0px; - background: transparent; -} - -/********** actionList **********/ - -QListView#actionList { - font-size: 20px; + background: #%scroll_color%; + border-radius: 1px; + min-height: 24px; } -QListView#actionList::item{ - height:28px; +QListView QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical, +QListView QScrollBar::up-arrow:vertical, QScrollBar::down-arrow:vertical, +QListView QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical { + border: 0px; + width: 0px; + height: 0px; + background: transparent; } /********** proposalList **********/ QListView#proposalList { - icon-size: 40px; - font-size: 22px; + icon-size: 40px; + font-size: 24px; } QListView#proposalList::item{ - height:48px; + padding: 8px 0px 0px 0px; +} + +/********** actionList **********/ + +QListView#actionList { + font-size: 20px; } diff -Nru albert-0.9.4/data/SlickTemplate.sh albert-0.10.1/data/SlickTemplate.sh --- albert-0.9.4/data/SlickTemplate.sh 2017-03-01 10:22:31.000000000 +0000 +++ albert-0.10.1/data/SlickTemplate.sh 2017-03-20 15:24:06.000000000 +0000 @@ -12,6 +12,6 @@ } #makeStyle bg fg button scroll selection output -makeStyle "$TEMPLATE" "fcfcfc" "000000" "bdbdbd" "e2e2e2" "eeeeee" "$1/Yosemite.qss" -makeStyle "$TEMPLATE" "f4000000" "ffffff" "484848" "484848" "262626" "$1/Yosemite Dark.qss" +makeStyle "$TEMPLATE" "fcfcfc" "808080" "e0e0e0" "c0c0c0" "e0e0e0" "$1/Spotlight.qss" +makeStyle "$TEMPLATE" "030303" "808080" "202020" "404040" "202020" "$1/Spotlight Dark.qss" diff -Nru albert-0.9.4/data/themes/Spotlight Dark.qss albert-0.10.1/data/themes/Spotlight Dark.qss --- albert-0.9.4/data/themes/Spotlight Dark.qss 1970-01-01 00:00:00.000000000 +0000 +++ albert-0.10.1/data/themes/Spotlight Dark.qss 2017-03-20 15:24:06.000000000 +0000 @@ -0,0 +1,87 @@ +/* + * author: Manuel Schneider + * + * Check http://doc.qt.io/qt-5/stylesheet-syntax.html especially the subtopics: + * The Style Sheet Syntax (http://doc.qt.io/qt-5/stylesheet-syntax.html) + * Qt Style Sheets Reference (http://doc.qt.io/qt-5/stylesheet-reference.html) + */ + +* { + border: none; + color : #808080; + background-color: #030303; +} + +#frame { + padding: 6px 0px; + border-radius: 8px; + background-color: #030303; + min-width:640px; + max-width:640px; +} + +#inputLine { + padding: 0px 8px; + font-size: 36px; + selection-color: #030303; + selection-background-color: #808080; + background-color: transparent; +} + +#settingsButton { + margin: 6px 6px 0px 0px; + color: #202020; + background-color: transparent; + padding: 2px; + min-width:14px; + min-height:14px; + max-width:14px; + max-height:14px; +} + +/********** ListViews ************/ + +QListView { + background: transparent; +} + +QListView::item:selected { + background: #202020; +} + +QListView QScrollBar:vertical { + width: 3px; + background: transparent; +} + +QListView QScrollBar::handle:vertical { + background: #404040; + border-radius: 1px; + min-height: 24px; +} + +QListView QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical, +QListView QScrollBar::up-arrow:vertical, QScrollBar::down-arrow:vertical, +QListView QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical { + border: 0px; + width: 0px; + height: 0px; + background: transparent; +} + +/********** proposalList **********/ + +QListView#proposalList { + icon-size: 40px; + font-size: 24px; +} + +QListView#proposalList::item{ + padding: 8px 0px 0px 0px; +} + +/********** actionList **********/ + +QListView#actionList { + font-size: 20px; +} diff -Nru albert-0.9.4/data/themes/Spotlight.qss albert-0.10.1/data/themes/Spotlight.qss --- albert-0.9.4/data/themes/Spotlight.qss 1970-01-01 00:00:00.000000000 +0000 +++ albert-0.10.1/data/themes/Spotlight.qss 2017-03-20 15:24:06.000000000 +0000 @@ -0,0 +1,87 @@ +/* + * author: Manuel Schneider + * + * Check http://doc.qt.io/qt-5/stylesheet-syntax.html especially the subtopics: + * The Style Sheet Syntax (http://doc.qt.io/qt-5/stylesheet-syntax.html) + * Qt Style Sheets Reference (http://doc.qt.io/qt-5/stylesheet-reference.html) + */ + +* { + border: none; + color : #808080; + background-color: #fcfcfc; +} + +#frame { + padding: 6px 0px; + border-radius: 8px; + background-color: #fcfcfc; + min-width:640px; + max-width:640px; +} + +#inputLine { + padding: 0px 8px; + font-size: 36px; + selection-color: #fcfcfc; + selection-background-color: #808080; + background-color: transparent; +} + +#settingsButton { + margin: 6px 6px 0px 0px; + color: #e0e0e0; + background-color: transparent; + padding: 2px; + min-width:14px; + min-height:14px; + max-width:14px; + max-height:14px; +} + +/********** ListViews ************/ + +QListView { + background: transparent; +} + +QListView::item:selected { + background: #e0e0e0; +} + +QListView QScrollBar:vertical { + width: 3px; + background: transparent; +} + +QListView QScrollBar::handle:vertical { + background: #c0c0c0; + border-radius: 1px; + min-height: 24px; +} + +QListView QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical, +QListView QScrollBar::up-arrow:vertical, QScrollBar::down-arrow:vertical, +QListView QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical { + border: 0px; + width: 0px; + height: 0px; + background: transparent; +} + +/********** proposalList **********/ + +QListView#proposalList { + icon-size: 40px; + font-size: 24px; +} + +QListView#proposalList::item{ + padding: 8px 0px 0px 0px; +} + +/********** actionList **********/ + +QListView#actionList { + font-size: 20px; +} diff -Nru albert-0.9.4/data/themes/Spotlight Space.qss albert-0.10.1/data/themes/Spotlight Space.qss --- albert-0.9.4/data/themes/Spotlight Space.qss 1970-01-01 00:00:00.000000000 +0000 +++ albert-0.10.1/data/themes/Spotlight Space.qss 2017-03-20 15:24:06.000000000 +0000 @@ -0,0 +1,93 @@ +/* + * author: Manuel Schneider + * + * Check http://doc.qt.io/qt-5/stylesheet-syntax.html especially the subtopics: + * The Style Sheet Syntax (http://doc.qt.io/qt-5/stylesheet-syntax.html) + * Qt Style Sheets Reference (http://doc.qt.io/qt-5/stylesheet-reference.html) + */ + +* { + border: none; + color : #ddd; + background-color: #444; +} + +#frame { + padding: 6px 0px; + border-radius: 8px; + min-width:640px; + max-width:640px; + spacing: 0px; +} + +#inputLine { + padding: 0px 8px; + font-size: 36px; + color : #0080ff; + selection-color: #ddd; + selection-background-color: #0060c0; + background-color: transparent; +} + +#settingsButton { + margin-top: 6px; + color: #444; + background-color: transparent; + padding: 2px; + min-width:14px; + min-height:14px; + max-width:14px; + max-height:14px; +} + +#settingsButton::hover { + background-color: #0080ff; + border-radius: 6px; +} + +/********** ListViews ************/ + +QListView { + background: transparent; +} + +QListView::item:selected { + background: #0060c0; +} + +QListView QScrollBar:vertical { + width: 3px; + background: transparent; +} + +QListView QScrollBar::handle:vertical { + background: #0080ff; + border-radius: 1px; + min-height: 24px; +} + +QListView QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical, +QListView QScrollBar::up-arrow:vertical, QScrollBar::down-arrow:vertical, +QListView QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical { + border: 0px; + width: 0px; + height: 0px; + background: transparent; +} + +/********** proposalList **********/ + +QListView#proposalList { + icon-size: 40px; + font-size: 24px; +} + +QListView#proposalList::item{ + padding: 8px 0px 0px 0px; +} + +/********** actionList **********/ + +QListView#actionList { + font-size: 20px; +} diff -Nru albert-0.9.4/debian/changelog albert-0.10.1/debian/changelog --- albert-0.9.4/debian/changelog 2017-03-02 10:06:14.000000000 +0000 +++ albert-0.10.1/debian/changelog 2017-03-21 09:02:14.000000000 +0000 @@ -1,4 +1,22 @@ -albert (0.9.4-1~webupd8~vivid0) vivid; urgency=medium +albert (0.10.1-1~webupd8~vivid0) vivid; urgency=medium + + * New upstream release + + -- Alin Andrei Wed, 21 Mar 2017 11:02:14 +0200 + +albert (0.10.0-1~webupd8~trusty0) trusty; urgency=medium + + * New upstream release + + -- Alin Andrei Mon, 20 Mar 2017 11:40:29 +0200 + +albert (0.9.5-1~webupd8~yakkety0) yakkety; urgency=medium + + * New upstream bugfix release + + -- Alin Andrei Tue, 14 Mar 2017 11:19:39 +0100 + +albert (0.9.4-1~webupd8~trusty0) trusty; urgency=medium * New upstream bugfix release diff -Nru albert-0.9.4/debian/control albert-0.10.1/debian/control --- albert-0.9.4/debian/control 2017-01-31 10:40:24.000000000 +0000 +++ albert-0.10.1/debian/control 2017-03-20 10:08:12.000000000 +0000 @@ -8,6 +8,6 @@ Package: albert Architecture: any -Depends: ${shlibs:Depends}, ${misc:Depends}, libqt5sql5-sqlite +Depends: ${shlibs:Depends}, ${misc:Depends}, libqt5sql5-sqlite, libqt5concurrent5 Description: Albert Launcher An amazing, desktop environment agnostic omnilauncher. diff -Nru albert-0.9.4/src/application/src/main.cpp albert-0.10.1/src/application/src/main.cpp --- albert-0.9.4/src/application/src/main.cpp 2017-03-01 10:22:31.000000000 +0000 +++ albert-0.10.1/src/application/src/main.cpp 2017-03-20 15:24:06.000000000 +0000 @@ -66,7 +66,7 @@ app = new QApplication(argc, argv); app->setApplicationName("albert"); app->setApplicationDisplayName("Albert"); - app->setApplicationVersion("v0.9.4"); + app->setApplicationVersion("v0.10.1"); app->setQuitOnLastWindowClosed(false); QString icon = XdgIconLookup::iconPath("albert"); if ( icon.isEmpty() ) icon = ":app_icon"; @@ -240,9 +240,14 @@ * START IPC SERVER */ - // Start server so second instances will close - QLocalServer::removeServer(app->applicationName()); - localServer->listen(app->applicationName()); + // Remove pipes potentially leftover after crash + QLocalServer::removeServer(app->applicationName()); + + // Create server and handle messages + if ( !localServer->listen(app->applicationName()) ) + qWarning() << "Local server could not be created. IPC will not work! Reason:" << localServer->errorString(); + + // Handle incomin messages QObject::connect(localServer, &QLocalServer::newConnection, dispatchMessage); @@ -267,13 +272,27 @@ /* - * Hotkey + * Alfred demarcation */ QSettings settings(qApp->applicationName()); - QString hotkey; + bool alfred_note_shown = settings.value("alfred_note_shown", false).toBool(); + if ( !alfred_note_shown ) { + QMessageBox(QMessageBox::Information, "Note", + "This is free and open source software. We are " + "not affiliated with Alfred or Running with " + "Crayons Ltd. Please do not bother them with " + "support questions. They cannot help you.").exec(); + settings.setValue("alfred_note_shown", true); + } + + + /* + * Hotkey + */ // Check for a command line override + QString hotkey; if ( parser.isSet("hotkey") ) { hotkey = parser.value("hotkey"); if ( !hotkeyManager->registerHotkey(hotkey) ) @@ -391,6 +410,8 @@ delete mainWindow; delete ExtensionManager::instance; + localServer->close(); + // Delete the running indicator file QFile::remove(QStandardPaths::writableLocation(QStandardPaths::CacheLocation)+"/running"); diff -Nru albert-0.9.4/src/application/src/mainwindow/mainwindow.cpp albert-0.10.1/src/application/src/mainwindow/mainwindow.cpp --- albert-0.9.4/src/application/src/mainwindow/mainwindow.cpp 2017-03-01 10:22:31.000000000 +0000 +++ albert-0.10.1/src/application/src/mainwindow/mainwindow.cpp 2017-03-20 15:24:06.000000000 +0000 @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -167,18 +168,9 @@ QObject::connect(ui.proposalList, &ProposalList::activated, [this](const QModelIndex &index){ switch (qApp->queryKeyboardModifiers()) { - case Qt::AltModifier: // AltAction + case Qt::MetaModifier: // Default fallback action (Meta) ui.proposalList->model()->setData(index, -1, Qt::UserRole+101); break; - case Qt::MetaModifier: // MetaAction - ui.proposalList->model()->setData(index, -1, Qt::UserRole+102); - break; - case Qt::ControlModifier: // ControlAction - ui.proposalList->model()->setData(index, -1, Qt::UserRole+103); - break; - case Qt::ShiftModifier: // ShiftAction - ui.proposalList->model()->setData(index, -1, Qt::UserRole+104); - break; default: // DefaultAction ui.proposalList->model()->setData(index, -1, Qt::UserRole+100); break; @@ -195,6 +187,7 @@ history_->add(ui.inputLine->text()); ui.proposalList->model()->setData(ui.proposalList->currentIndex(), index.row(), Qt::UserRole); this->setVisible(false); + ui.inputLine->clear(); }); } @@ -530,13 +523,23 @@ /** ***************************************************************************/ bool MainWindow::eventFilter(QObject *, QEvent *event) { - if (event->type() == QEvent::KeyPress) { + if ( event->type() == QEvent::KeyPress ) { QKeyEvent* keyEvent = static_cast(event); switch (keyEvent->key()) { // Toggle actionsview case Qt::Key_Tab: - setShowActions(!actionsAreShown()); + // see query.cpp for userroles + if ( ui.proposalList->currentIndex().isValid() ) + ui.inputLine->setText( + ui.proposalList->model()->data( + ui.proposalList->currentIndex(), Qt::UserRole+1 + ).toString() + ); + return true; + + case Qt::Key_Alt: + setShowActions(true); return true; case Qt::Key_Up:{ @@ -563,6 +566,29 @@ } } } + + if ( event->type() == QEvent::KeyRelease ) { + QKeyEvent* keyEvent = static_cast(event); + switch (keyEvent->key()) { + case Qt::Key_Alt: + setShowActions(false); + return true; + } + } + + if (event->type() == QEvent::Wheel) { + QWheelEvent* wheelEvent = static_cast(event); + if ( wheelEvent->angleDelta().y() > 0 ) { + QString next = history_->next(); + if (!next.isEmpty()) + ui.inputLine->setText(next); + } else { + QString prev = history_->prev(); + if (!prev.isEmpty()) + ui.inputLine->setText(prev); + } + } + return false; } diff -Nru albert-0.9.4/src/application/src/mainwindow/proposallist.cpp albert-0.10.1/src/application/src/mainwindow/proposallist.cpp --- albert-0.9.4/src/application/src/mainwindow/proposallist.cpp 2017-03-01 10:22:31.000000000 +0000 +++ albert-0.10.1/src/application/src/mainwindow/proposallist.cpp 2017-03-20 15:24:06.000000000 +0000 @@ -72,18 +72,9 @@ case Qt::Key_Alt: case Qt::Key_Meta: switch (keyEvent->modifiers()) { - case Qt::AltModifier: // AltAction + case Qt::MetaModifier: // Default fallback action (Meta) delegate_->subTextRole = Qt::UserRole+101; break; - case Qt::MetaModifier: // MetaAction - delegate_->subTextRole = Qt::UserRole+102; - break; - case Qt::ControlModifier: // ControlAction - delegate_->subTextRole = Qt::UserRole+103; - break; - case Qt::ShiftModifier: // ShiftAction - delegate_->subTextRole = Qt::UserRole+104; - break; default: // DefaultAction delegate_->subTextRole = Qt::ToolTipRole; break; @@ -114,18 +105,9 @@ case Qt::Key_Alt: case Qt::Key_Meta: switch (keyEvent->modifiers()) { - case Qt::AltModifier: // AltAction + case Qt::MetaModifier: // Default fallback action (Meta) delegate_->subTextRole = Qt::UserRole+101; break; - case Qt::MetaModifier: // MetaAction - delegate_->subTextRole = Qt::UserRole+102; - break; - case Qt::ControlModifier: // ControlAction - delegate_->subTextRole = Qt::UserRole+103; - break; - case Qt::ShiftModifier: // ShiftAction - delegate_->subTextRole = Qt::UserRole+104; - break; default: // DefaultAction delegate_->subTextRole = Qt::ToolTipRole; break; diff -Nru albert-0.9.4/src/application/src/settingswidget/settingswidget.cpp albert-0.10.1/src/application/src/settingswidget/settingswidget.cpp --- albert-0.9.4/src/application/src/settingswidget/settingswidget.cpp 2017-03-01 10:22:31.000000000 +0000 +++ albert-0.10.1/src/application/src/settingswidget/settingswidget.cpp 2017-03-20 15:24:06.000000000 +0000 @@ -253,7 +253,8 @@ ui.label_pluginTitle->show(); } else{ - QLabel *lbl = new QLabel("Plugin not loaded."); + QString msg("Plugin not loaded.\n%1"); + QLabel *lbl = new QLabel(msg.arg(extensionManager_->extensionSpecs()[current.row()]->lastError())); lbl->setEnabled(false); lbl->setAlignment(Qt::AlignCenter); ui.widget_pluginInfos->layout()->addWidget(lbl); diff -Nru albert-0.9.4/src/application/src/settingswidget/settingswidget.ui albert-0.10.1/src/application/src/settingswidget/settingswidget.ui --- albert-0.9.4/src/application/src/settingswidget/settingswidget.ui 2017-03-01 10:22:31.000000000 +0000 +++ albert-0.10.1/src/application/src/settingswidget/settingswidget.ui 2017-03-20 15:24:06.000000000 +0000 @@ -2,6 +2,14 @@ SettingsDialog + + + 0 + 0 + 720 + 400 + + 720 @@ -581,8 +589,9 @@ </head> <body> <h2>Albert launcher ___versionstring___</h2> -<p>If you encounter bugs or think you have suggestions for improvement, tell me at the <a href="https://github.com/ManuelSchneid3r/albert/issues">Github issue tracker.</a></p> +<p>If you encounter bugs or think you have suggestions for improvement, tell me at <a href="https://github.com/ManuelSchneid3r/albert/issues">Github</a>.</p> <p>If you really like this software please consider a donation via <a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&amp;hosted_button_id=W74BQPKPGNSNC">PayPal</a> or become a <a href="https://www.patreon.com/albertlauncher">patron</a>.</p> +<p>I'd like to thank all <a href="https://github.com/albertlauncher/albert/graphs/contributors">contributors</a>, <a href="https://albertlauncher.github.io/docs/contributing/#supporters">supporters</a> and users. You keep this project going on.</p> </body> </html> diff -Nru albert-0.9.4/src/lib/albert/include/item.h albert-0.10.1/src/lib/albert/include/item.h --- albert-0.9.4/src/lib/albert/include/item.h 2017-03-01 10:22:31.000000000 +0000 +++ albert-0.10.1/src/lib/albert/include/item.h 2017-03-20 15:24:06.000000000 +0000 @@ -54,6 +54,9 @@ /** The declarative subtext for the item */ virtual QString subtext() const = 0; + /** The string to use for completion */ + virtual QString completionString() const { return text(); } + /** Urgency level of the item, defautls to "Normal" */ virtual Urgency urgency() const { return Urgency::Normal; } diff -Nru albert-0.9.4/src/lib/albert/include/standarditem.h albert-0.10.1/src/lib/albert/include/standarditem.h --- albert-0.9.4/src/lib/albert/include/standarditem.h 2017-03-01 10:22:31.000000000 +0000 +++ albert-0.10.1/src/lib/albert/include/standarditem.h 2017-03-20 15:24:06.000000000 +0000 @@ -38,23 +38,27 @@ QString id() const override final; - QString text() const override final; + QString text() const override; void setText(const QString &text); - QString subtext() const override final; + QString subtext() const override; void setSubtext(const QString &subtext); - QString iconPath() const override final; + QString completionString() const override; + void setCompletionString(const QString &completion); + + QString iconPath() const override; void setIconPath( const QString &iconPath); - std::vector> actions() override final; + std::vector> actions() override; void setActions(std::vector> &&actions); -private: +protected: QString id_; QString text_; QString subtext_; + QString completion_; QString iconPath_; std::vector> actions_; diff -Nru albert-0.9.4/src/lib/albert/src/pluginsystem/extensionmanager.cpp albert-0.10.1/src/lib/albert/src/pluginsystem/extensionmanager.cpp --- albert-0.9.4/src/lib/albert/src/pluginsystem/extensionmanager.cpp 2017-03-01 10:22:31.000000000 +0000 +++ albert-0.10.1/src/lib/albert/src/pluginsystem/extensionmanager.cpp 2017-03-20 15:24:06.000000000 +0000 @@ -135,7 +135,7 @@ for (unique_ptr & extensionSpec : d->extensionSpecs_){ QString configName = QString("%1/enabled").arg(extensionSpec->id()); if ( (settings.contains(configName) && settings.value(configName).toBool()) - || extensionSpec->enabledByDefault() ) + || (!settings.contains(configName) && extensionSpec->enabledByDefault()) ) loadExtension(extensionSpec); } } @@ -156,10 +156,11 @@ /** ***************************************************************************/ void Core::ExtensionManager::loadExtension(const unique_ptr &spec) { if (spec->state() != ExtensionSpec::State::Loaded){ - system_clock::time_point start = system_clock::now(); +// system_clock::time_point start = system_clock::now(); if ( spec->load() ) { - auto msecs = std::chrono::duration_cast(system_clock::now()-start); - qDebug() << QString("Loading %1 done in %2 milliseconds").arg(spec->id()).arg(msecs.count()).toLocal8Bit().data(); +// TODO wrtie to database +// auto msecs = std::chrono::duration_cast(system_clock::now()-start); +// qDebug() << QString("Loading %1 done in %2 milliseconds").arg(spec->id()).arg(msecs.count()).toLocal8Bit().data(); d->extensions_.insert(spec->instance()); } else qDebug() << QString("Loading %1 failed. (%2)").arg(spec->id(), spec->lastError()).toLocal8Bit().data(); @@ -194,8 +195,8 @@ bool Core::ExtensionManager::extensionIsEnabled(const unique_ptr &extensionSpec) { QSettings settings(qApp->applicationName()); QString configName = QString("%1/enabled").arg(extensionSpec->id()); - return (settings.contains(configName) && settings.value(configName).toBool()) - || extensionSpec->enabledByDefault(); + return ( (settings.contains(configName) && settings.value(configName).toBool()) + || (!settings.contains(configName) && extensionSpec->enabledByDefault()) ); } diff -Nru albert-0.9.4/src/lib/albert/src/pluginsystem/query.cpp albert-0.10.1/src/lib/albert/src/pluginsystem/query.cpp --- albert-0.9.4/src/lib/albert/src/pluginsystem/query.cpp 2017-03-01 10:22:31.000000000 +0000 +++ albert-0.10.1/src/lib/albert/src/pluginsystem/query.cpp 2017-03-20 15:24:06.000000000 +0000 @@ -252,6 +252,8 @@ actionTexts.append(action->text()); return actionTexts; } + case Qt::UserRole+1: // Completion string + return item->completionString(); case Qt::UserRole+100: // DefaultAction return (0 < static_cast(item->actions().size())) ? item->actions()[0]->text() : item->subtext(); @@ -293,25 +295,12 @@ if (0U < item->actions().size()) item->actions()[0]->activate(); break; - case Qt::UserRole+101: // AltAction + case Qt::UserRole+101: // Default fallback action (Meta) if (0U < fallbacks.size() && 0U < item->actions().size()) { fallbacks[0]->actions()[0]->activate(); itemId = fallbacks[0]->id(); } break; - case Qt::UserRole+102: // MetaAction - if (1U < item->actions().size()) - item->actions()[1]->activate(); - break; - case Qt::UserRole+103: // ControlAction - if (2U < item->actions().size()) - item->actions()[2]->activate(); - break; - case Qt::UserRole+104: // ShiftAction - if (3U < item->actions().size()) - item->actions()[3]->activate(); - break; - } // Save usage diff -Nru albert-0.9.4/src/lib/albert/src/standardobjects/standarditem.cpp albert-0.10.1/src/lib/albert/src/standardobjects/standarditem.cpp --- albert-0.9.4/src/lib/albert/src/standardobjects/standarditem.cpp 2017-03-01 10:22:31.000000000 +0000 +++ albert-0.10.1/src/lib/albert/src/standardobjects/standarditem.cpp 2017-03-20 15:24:06.000000000 +0000 @@ -41,6 +41,14 @@ subtext_ = subtext; } +QString Core::StandardItem::completionString() const { + return (completion_.isNull()) ? text_ : completion_; +} + +void Core::StandardItem::setCompletionString(const QString &completion) { + completion_ = completion; +} + QString Core::StandardItem::iconPath() const { return iconPath_; } diff -Nru albert-0.9.4/src/plugins/applications/configwidget.ui albert-0.10.1/src/plugins/applications/configwidget.ui --- albert-0.9.4/src/plugins/applications/configwidget.ui 2017-03-01 10:22:31.000000000 +0000 +++ albert-0.10.1/src/plugins/applications/configwidget.ui 2017-03-20 15:24:06.000000000 +0000 @@ -22,7 +22,7 @@ </head> <body> <p>Applications are looked up in the &quot;<span style=" font-style:italic;">applications/&quot;</span> directories in the $XDG_DATA_HOME and $XDG_DATA_DIRS, which are set in the environment variables. Your current environment configuration results in the following applications directories: <span style=" font-weight:600; font-style:italic;">__XDG_DATA_DIRS__</span>. </p> -<p>Every application is represented by a desktop file which has an ID. The desktop file ID is built using the path of the desktop file relative to the applications directory and turning '/' into '-'. If multiple files have the same desktop file ID, the first one in the precedence order given above is used.</p></body></html> +<p>Every application is represented by a desktop file which has an ID. The desktop file ID is built using the path of the desktop file relative to the applications directory and turning '/' into '-'. If multiple files have the same desktop file ID, the first one in the precedence order given above is used. For mor details check the <a href="https://specifications.freedesktop.org/desktop-entry-spec/latest/">desktop entry sprecificion</a>.</p></body></html> true @@ -34,17 +34,34 @@ - - - Fuzzy - - + + + + + Ignore OnlyShowIn/NotShowIn keys + + + + + + + Fuzzy + + + + Qt::Horizontal + + + 0 + 0 + + @@ -54,6 +71,12 @@ Qt::Vertical + + + 0 + 0 + + diff -Nru albert-0.9.4/src/plugins/applications/src/main.cpp albert-0.10.1/src/plugins/applications/src/main.cpp --- albert-0.9.4/src/plugins/applications/src/main.cpp 2017-03-01 10:22:31.000000000 +0000 +++ albert-0.10.1/src/plugins/applications/src/main.cpp 2017-03-20 15:24:06.000000000 +0000 @@ -52,9 +52,10 @@ namespace { -const char* CFG_FUZZY = "fuzzy"; -const bool DEF_FUZZY = false; -const uint UPDATE_DELAY = 60000; +const char* CFG_FUZZY = "fuzzy"; +const bool DEF_FUZZY = false; +const char* CFG_IGNORESHOWINKEYS = "ignore_show_in_keys"; +const bool DEF_IGNORESHOWINKEYS = false; /******************************************************************************/ QStringList expandedFieldCodes(const QStringList & unexpandedFields, @@ -259,7 +260,7 @@ /** ***************************************************************************/ -vector> indexApplications() { +vector> indexApplications(bool ignoreShowInKeys) { // Get a new index [O(n)] vector> desktopEntries; @@ -337,22 +338,24 @@ && entryIterator->second == "true") continue; - // Skip if the current desktop environment is specified in "NotShowIn" - if ((entryIterator = entryMap.find("NotShowIn")) != entryMap.end()) - for (const QString &str : entryIterator->second.split(';',QString::SkipEmptyParts)) - if (xdg_current_desktop.contains(str)) + if (!ignoreShowInKeys) { + // Skip if the current desktop environment is specified in "NotShowIn" + if ((entryIterator = entryMap.find("NotShowIn")) != entryMap.end()) + for (const QString &str : entryIterator->second.split(';',QString::SkipEmptyParts)) + if (xdg_current_desktop.contains(str)) + continue; + + // Skip if the current desktop environment is not specified in "OnlyShowIn" + if ((entryIterator = entryMap.find("OnlyShowIn")) != entryMap.end()) { + bool found = false; + for (const QString &str : entryIterator->second.split(';',QString::SkipEmptyParts)) + if (xdg_current_desktop.contains(str)){ + found = true; + break; + } + if (!found) continue; - - // Skip if the current desktop environment is not specified in "OnlyShowIn" - if ((entryIterator = entryMap.find("OnlyShowIn")) != entryMap.end()) { - bool found = false; - for (const QString &str : entryIterator->second.split(';',QString::SkipEmptyParts)) - if (xdg_current_desktop.contains(str)){ - found = true; - break; - } - if (!found) - continue; + } } bool term; @@ -589,10 +592,12 @@ vector> index; OfflineIndex offlineIndex; - QTimer updateDelayTimer; + QFutureWatcher>> futureWatcher; + bool rerun = false; + bool ignoreShowInKeys; + void finishIndexing(); void startIndexing(); - QFutureWatcher>> futureWatcher; }; @@ -601,8 +606,10 @@ void Applications::ApplicationsPrivate::startIndexing() { // Never run concurrent - if ( futureWatcher.future().isRunning() ) + if ( futureWatcher.future().isRunning() ) { + rerun = true; return; + } // Run finishIndexing when the indexing thread finished futureWatcher.disconnect(); @@ -610,12 +617,11 @@ std::bind(&ApplicationsPrivate::finishIndexing, this)); // Run the indexer thread - futureWatcher.setFuture(QtConcurrent::run(indexApplications)); + futureWatcher.setFuture(QtConcurrent::run(indexApplications, ignoreShowInKeys)); // Notification - qDebug() << qPrintable(QString("[%1] Start indexing in background thread.").arg(q->Core::Extension::id).toUtf8().constData()); + qDebug() << "Start indexing applications."; emit q->statusInfo("Indexing applications ..."); - } @@ -643,8 +649,13 @@ } // Notification - qDebug() << qPrintable(QString("[%1] Indexing done (%2 items).").arg(q->Core::Extension::id).arg(index.size())); + qDebug() << qPrintable(QString("Indexed %1 applications.").arg(index.size())); emit q->statusInfo(QString("%1 applications indexed.").arg(index.size())); + + if ( rerun ) { + startIndexing(); + rerun = false; + } } @@ -664,17 +675,10 @@ QSettings s(qApp->applicationName()); s.beginGroup(Core::Extension::id); d->offlineIndex.setFuzzy(s.value(CFG_FUZZY, DEF_FUZZY).toBool()); + d->ignoreShowInKeys = s.value(CFG_IGNORESHOWINKEYS, DEF_IGNORESHOWINKEYS).toBool(); - // Delay the indexing to avoid excessice resource consumption - d->updateDelayTimer.setInterval(UPDATE_DELAY); - d->updateDelayTimer.setSingleShot(true); - - // If the filesystem changed, trigger the update delay + // If the filesystem changed, trigger the scan connect(&d->watcher, &QFileSystemWatcher::directoryChanged, - &d->updateDelayTimer, static_cast(&QTimer::start)); - - // If the update delay passed, update the index - connect(&d->updateDelayTimer, &QTimer::timeout, std::bind(&ApplicationsPrivate::startIndexing, d.get())); // Trigger initial update @@ -697,7 +701,17 @@ // Fuzzy d->widget->ui.checkBox_fuzzy->setChecked(d->offlineIndex.fuzzy()); - connect(d->widget->ui.checkBox_fuzzy, &QCheckBox::toggled, this, &Extension::setFuzzy); + connect(d->widget->ui.checkBox_fuzzy, &QCheckBox::toggled, + this, &Extension::setFuzzy); + + // Ignore onlyshowin notshowin keys + d->widget->ui.checkBox_ignoreShowInKeys->setChecked(d->ignoreShowInKeys); + connect(d->widget->ui.checkBox_ignoreShowInKeys, &QCheckBox::toggled, + this, [this](bool checked){ + QSettings(qApp->applicationName()).setValue(QString("%1/%2").arg(Core::Extension::id, CFG_IGNORESHOWINKEYS), checked); + d->ignoreShowInKeys = checked ; + d->startIndexing(); + }); // Status bar ( d->futureWatcher.isRunning() ) diff -Nru albert-0.9.4/src/plugins/chromebookmarks/metadata.json albert-0.10.1/src/plugins/chromebookmarks/metadata.json --- albert-0.9.4/src/plugins/chromebookmarks/metadata.json 2017-03-01 10:22:31.000000000 +0000 +++ albert-0.10.1/src/plugins/chromebookmarks/metadata.json 2017-03-20 15:24:06.000000000 +0000 @@ -1,6 +1,6 @@ { "id" : "org.albert.extension.chromebookmarks", - "name" : "ChromeBookmarks", + "name" : "Chrome bookmarks", "version" : "1.0", "platform" : "Linux", "group" : "Extensions", diff -Nru albert-0.9.4/src/plugins/chromebookmarks/src/main.cpp albert-0.10.1/src/plugins/chromebookmarks/src/main.cpp --- albert-0.9.4/src/plugins/chromebookmarks/src/main.cpp 2017-03-01 10:22:31.000000000 +0000 +++ albert-0.10.1/src/plugins/chromebookmarks/src/main.cpp 2017-03-20 15:24:06.000000000 +0000 @@ -121,7 +121,7 @@ QFile f(bookmarksPath); if (!f.open(QIODevice::ReadOnly)) { - qWarning() << qPrintable(QString("Could not open %1").arg(bookmarksPath)); + qWarning() << qPrintable(QString("Could not open Chrome bookmarks file '%1'.").arg(bookmarksPath)); return vector>(); } @@ -181,7 +181,7 @@ futureWatcher.setFuture(QtConcurrent::run(indexChromeBookmarks, bookmarksFile)); // Notification - qDebug() << qPrintable(QString("[%1] Start indexing in background thread.").arg(q->Core::Extension::id)); + qDebug() << "Start indexing Chrome bookmarks."; emit q->statusInfo("Indexing bookmarks ..."); } @@ -208,10 +208,10 @@ */ if ( fileSystemWatcher.files().empty() ) if( !fileSystemWatcher.addPath(bookmarksFile)) - qWarning() << qPrintable(QString("%1 could not be watched. Changes in this path will not be noticed.").arg(bookmarksFile)); + qWarning() << qPrintable(QString("%1 can not be watched. Changes in this path will not be noticed.").arg(bookmarksFile)); // Notification - qDebug() << qPrintable(QString("[%1] Indexing done (%2 items).").arg(q->Core::Extension::id).arg(index.size())); + qDebug() << qPrintable(QString("Indexed %1 Chrome bookmarks.").arg(index.size())); emit q->statusInfo(QString("%1 bookmarks indexed.").arg(index.size())); } diff -Nru albert-0.9.4/src/plugins/CMakeLists.txt albert-0.10.1/src/plugins/CMakeLists.txt --- albert-0.9.4/src/plugins/CMakeLists.txt 2017-03-01 10:22:31.000000000 +0000 +++ albert-0.10.1/src/plugins/CMakeLists.txt 2017-03-20 15:24:06.000000000 +0000 @@ -8,6 +8,8 @@ add_subdirectory(externalextensions) add_subdirectory(files) add_subdirectory(firefoxbookmarks) +add_subdirectory(ssh) +add_subdirectory(mpris) add_subdirectory(system) add_subdirectory(terminal) add_subdirectory(virtualbox) diff -Nru albert-0.9.4/src/plugins/create_plugin.py albert-0.10.1/src/plugins/create_plugin.py --- albert-0.9.4/src/plugins/create_plugin.py 1970-01-01 00:00:00.000000000 +0000 +++ albert-0.10.1/src/plugins/create_plugin.py 2017-03-20 15:24:06.000000000 +0000 @@ -0,0 +1,128 @@ +#!/usr/bin/python + +import os +import re +import sys +import string +from shutil import copyfile + +ID_KEYWORD = "projectid" +NAMESPACE_KEYWORD = "ProjectNamespace" +PRETTYNAME_KEYWORD = "Template" +ID_PATTERN = "^([a-z0-9]+)$" +NAMESPACE_PATTERN = "^([A-Za-z][A-Za-z0-9]+)$" +PRETTYNAME_PATTERN = "^([A-Za-z0-9 _\\-]+)$" +TEMPLATE_EXTENSION_BASE = "templateExtension/" +CMAKE_PATTERN = "^add_subdirectory\(([^\)]+)\)$" + +if len(sys.argv) != 4: + u = "Usage: create_plugin.py \n" + sys.stderr.write(u) + sys.exit(1) + +id_regex = re.compile(ID_PATTERN) +namespace_regex = re.compile(NAMESPACE_PATTERN) +prettyname_regex = re.compile(PRETTYNAME_PATTERN) +cmake_regex = re.compile(CMAKE_PATTERN) + +id_string = sys.argv[1] +namespace_string = sys.argv[2] +prettyname_string = sys.argv[3] + +if not id_regex.match(id_string): + e = "ID has to match " + ID_PATTERN + "\n" + sys.stderr.write(e) + sys.exit(1) + +if not namespace_regex.match(namespace_string): + e = "Namespace has to match " + NAMESPACE_PATTERN + "\n" + sys.stderr.write(e) + sys.exit(1) + +if not prettyname_regex.match(prettyname_string): + e = "Pretty Name has to match " + PRETTYNAME_PATTERN + "\n" + sys.stderr.write(e) + sys.exit(1) + +raw_input("Are we in the src/plugins directory? If not do not proceed because it won't work! ") + +print("Creating directory . . .") +os.mkdir(id_string) +os.chdir(id_string) + +baseDir = os.path.join("..", TEMPLATE_EXTENSION_BASE) +filesToPrepare = [] + +def scanDir(toscan): + global filesToPrepare + global baseDir + if toscan: + template = os.path.join(baseDir, toscan) + else: + template = baseDir + ext = toscan + files = os.listdir(template) + for nextFile in files: + path = os.path.join(template, nextFile) + pathNew = os.path.join(ext, nextFile) + if os.path.isdir(path): + print("Creating directory " + pathNew) + os.mkdir(pathNew) + scanDir(os.path.join(toscan, nextFile)) + else: + print("Copying file " + pathNew) + copyfile(path, pathNew) + filesToPrepare.append(pathNew) + +scanDir("") + +for localFile in filesToPrepare: + print("Preparing file " + localFile) + with open(localFile) as fd: + tmpfile = localFile + ".tmp" + tmp = open(tmpfile, "w") + for line in fd: + tmp.write(re.sub(ID_KEYWORD, id_string, + re.sub(NAMESPACE_KEYWORD, namespace_string, + re.sub(PRETTYNAME_KEYWORD, prettyname_string, line)))) + tmp.close() + os.rename(tmpfile, localFile) + +print("Leaving directory . . .") +os.chdir("..") +print("Updating CMakeLists.txt . . . ") +existingExtensions = [] +preLines = [] +postLines = [] +preSubdir = True +postSubdir = False +with open("CMakeLists.txt", "r") as makelist: + for line in makelist: + match = cmake_regex.match(line) + if match: + preSubdir = False + existingExtensions.append(match.group(1)) + else: + postSubdir = not preSubdir + + if preSubdir: + preLines.append(line) + elif postSubdir: + postLines.append(line) + +existingExtensions.append(id_string) +existingExtensions.sort() + +cmakefile = open("CMakeLists.txt", "w") +for line in preLines: + cmakefile.write(line) # The newline is already in the line, because it didn't get stripped + +for ext in existingExtensions: + cmakefile.write("add_subdirectory(") + cmakefile.write(ext) + cmakefile.write(")\n") + +for line in postLines: + cmakefile.write(line) # The newline is already in the line, because it didn't get stripped + +cmakefile.close() diff -Nru albert-0.9.4/src/plugins/debug/CMakeLists.txt albert-0.10.1/src/plugins/debug/CMakeLists.txt --- albert-0.9.4/src/plugins/debug/CMakeLists.txt 2017-03-01 10:22:31.000000000 +0000 +++ albert-0.10.1/src/plugins/debug/CMakeLists.txt 2017-03-20 15:24:06.000000000 +0000 @@ -4,7 +4,9 @@ FILE(GLOB_RECURSE SRC src/* metadata.json) -find_package(Qt5Widgets 5.2 REQUIRED) +find_package(Qt5 5.2.0 REQUIRED COMPONENTS + Widgets +) set(LIB ${Qt5Widgets_LIBRARIES} diff -Nru albert-0.9.4/src/plugins/externalextensions/src/externalextension.cpp albert-0.10.1/src/plugins/externalextensions/src/externalextension.cpp --- albert-0.9.4/src/plugins/externalextensions/src/externalextension.cpp 2017-03-01 10:22:31.000000000 +0000 +++ albert-0.10.1/src/plugins/externalextensions/src/externalextension.cpp 2017-03-20 15:24:06.000000000 +0000 @@ -196,7 +196,7 @@ // Finally save the variables, if any if ( !saveVariables(&object, &variables_, &errorString) ) - qWarning() << QString("Initialization: %1 (%2)").arg(errorString, path_).toLocal8Bit().data(); + qWarning() << qPrintable(QString("Initialization: %1 (%2)").arg(errorString, path_)); } @@ -212,7 +212,7 @@ // Run the process variables_["ALBERT_OP"] = "FINALIZE"; if ( !runProcess(path_, &variables_, &out, &errorString) ) { - qWarning() << QString("Finalization failed: %1 (%2)").arg(errorString, path_).toLocal8Bit().data(); + qWarning() << qPrintable(QString("Finalization failed: %1 (%2)").arg(errorString, path_)); return; } @@ -221,13 +221,13 @@ // Parse stdout if ( !parseJsonObject(out, &object, &errorString) ) { - qWarning() << QString("Finalization failed: %1 (%2)").arg(errorString, path_).toLocal8Bit().data(); + qWarning() << qPrintable(QString("Finalization failed: %1 (%2)").arg(errorString, path_)); return; } // Save the variables, if any if ( !saveVariables(&object, &variables_, &errorString) ){ - qWarning() << QString("Finalization: %1 (%2)").arg(errorString, path_).toLocal8Bit().data(); + qWarning() << qPrintable(QString("Finalization: %1 (%2)").arg(errorString, path_)); return; } } @@ -245,7 +245,7 @@ // Run the process variables_["ALBERT_OP"] = "SETUPSESSION"; if ( !runProcess(path_, &variables_, &out, &errorString) ) { - qWarning() << QString("Session setup failed: %1 (%2)").arg(errorString, path_).toLocal8Bit().data(); + qWarning() << qPrintable(QString("Session setup failed: %1 (%2)").arg(errorString, path_)); return; } @@ -254,13 +254,13 @@ // Parse stdout if ( !parseJsonObject(out, &object, &errorString) ) { - qWarning() << QString("Session setup failed: %1 (%2)").arg(errorString, path_).toLocal8Bit().data(); + qWarning() << qPrintable(QString("Session setup failed: %1 (%2)").arg(errorString, path_)); return; } // Save the variables, if any if ( !saveVariables(&object, &variables_, &errorString) ){ - qWarning() << QString("Session setup: %1 (%2)").arg(errorString, path_).toLocal8Bit().data(); + qWarning() << qPrintable(QString("Session setup: %1 (%2)").arg(errorString, path_)); return; } } @@ -278,7 +278,7 @@ // Run the process variables_["ALBERT_OP"] = "TEARDOWNSESSION"; if ( !runProcess(path_, &variables_, &out, &errorString) ) { - qWarning() << QString("Session teardown failed: %1 (%2)").arg(errorString, path_).toLocal8Bit().data(); + qWarning() << qPrintable(QString("Session teardown failed: %1 (%2)").arg(errorString, path_)); return; } @@ -287,13 +287,13 @@ // Parse stdout if ( !parseJsonObject(out, &object, &errorString) ) { - qWarning() << QString("Session teardown failed: %1 (%2)").arg(errorString, path_).toLocal8Bit().data(); + qWarning() << qPrintable(QString("Session teardown failed: %1 (%2)").arg(errorString, path_)); return; } // Save the variables, if any if ( !saveVariables(&object, &variables_, &errorString) ){ - qWarning() << QString("Session teardown: %1 (%2)").arg(errorString, path_).toLocal8Bit().data(); + qWarning() << qPrintable(QString("Session teardown: %1 (%2)").arg(errorString, path_)); return; } } @@ -312,13 +312,13 @@ variables_["ALBERT_OP"] = "QUERY"; variables_["ALBERT_QUERY"] = query->searchTerm(); if ( !runProcess(path_, &variables_, &out, &errorString) ) { - qWarning() << QString("Handle query failed: %1 (%2)").arg(errorString, path_).toLocal8Bit().data(); + qWarning() << qPrintable(QString("Handle query failed: %1 (%2)").arg(errorString, path_)); return; } // Parse stdout if ( !parseJsonObject(out, &object, &errorString) ) { - qWarning() << QString("Handle query failed: %1 (%2)").arg(errorString, path_).toLocal8Bit().data(); + qWarning() << qPrintable(QString("Handle query failed: %1 (%2)").arg(errorString, path_)); return; } @@ -327,19 +327,19 @@ // Save the variables, if any if ( !saveVariables(&object, &variables_, &errorString) ){ - qWarning() << QString("Handle query: %1 (%2)").arg(errorString, path_).toLocal8Bit().data(); + qWarning() << qPrintable(QString("Handle query: %1 (%2)").arg(errorString, path_)); return; } // Check existance of items if ( !object.contains("items") ) { - qWarning() << QString("Handle query failed: Result contains no items (%1)").arg(path_).toLocal8Bit().data(); + qWarning() << qPrintable(QString("Handle query failed: Result contains no items (%1)").arg(path_)); return; } // Check type of items if ( !object["items"].isArray() ) { - qWarning() << QString("Handle query failed: 'items' is not an array (%1)").arg(path_).toLocal8Bit().data(); + qWarning() << qPrintable(QString("Handle query failed: 'items' is not an array (%1)").arg(path_)); return; } @@ -352,7 +352,7 @@ for (const QJsonValue & itemValue : object["items"].toArray() ){ if ( !itemValue.isObject() ) { - qWarning("Item is not a json object. (%s)", path_.toLocal8Bit().data()); + qWarning() << qPrintable(QString("Item is not a json object. (%1)").arg(path_)); continue; } object = itemValue.toObject(); diff -Nru albert-0.9.4/src/plugins/files/src/file.cpp albert-0.10.1/src/plugins/files/src/file.cpp --- albert-0.9.4/src/plugins/files/src/file.cpp 2017-03-01 10:22:31.000000000 +0000 +++ albert-0.10.1/src/plugins/files/src/file.cpp 2017-03-20 15:24:06.000000000 +0000 @@ -17,6 +17,7 @@ #include #include #include +#include #include #include "file.h" #include "fileactions.h" @@ -41,13 +42,26 @@ /** ***************************************************************************/ +QString Files::File::completionString() const { + QString result = ( QFileInfo(path_).isDir() ) ? QString("%1/").arg(path_) : path_; +#ifdef __linux__ + if ( result.startsWith(QDir::homePath()) ) + result.replace(QDir::homePath(), "~"); +#endif + return result; +} + + + +/** ***************************************************************************/ QString Files::File::iconPath() const { const QString xdgIconName = mimetype_.iconName(); // First check if icon exists - if (iconCache_.count(xdgIconName)) - return iconCache_[xdgIconName]; + auto search = iconCache_.find(xdgIconName); + if(search != iconCache_.end()) + return search->second; QString iconPath; if ( !(iconPath = XdgIconLookup::iconPath(xdgIconName)).isNull() // Lookup iconName diff -Nru albert-0.9.4/src/plugins/files/src/file.h albert-0.10.1/src/plugins/files/src/file.h --- albert-0.9.4/src/plugins/files/src/file.h 2017-03-01 10:22:31.000000000 +0000 +++ albert-0.10.1/src/plugins/files/src/file.h 2017-03-20 15:24:06.000000000 +0000 @@ -39,6 +39,7 @@ QString id() const override { return path_; } QString text() const override; QString subtext() const override; + QString completionString() const override; QString iconPath() const override; std::vector indexKeywords() const override; std::vector> actions() override; diff -Nru albert-0.9.4/src/plugins/files/src/main.cpp albert-0.10.1/src/plugins/files/src/main.cpp --- albert-0.9.4/src/plugins/files/src/main.cpp 2017-03-01 10:22:31.000000000 +0000 +++ albert-0.10.1/src/plugins/files/src/main.cpp 2017-03-20 15:24:06.000000000 +0000 @@ -130,7 +130,7 @@ futureWatcher.setFuture(QtConcurrent::run(this, &FilesPrivate::indexFiles)); // Notification - qDebug() << qPrintable(QString("[%1] Start indexing in background thread.").arg(q->Core::Extension::id).toUtf8().constData()); + qDebug() << "Start indexing files."; emit q->statusInfo("Indexing files ..."); } @@ -150,7 +150,7 @@ offlineIndex.add(item); // Notification - qDebug() << qPrintable(QString("[%1] Indexing done (%2 items).").arg(q->Core::Extension::id).arg(index.size())); + qDebug() << qPrintable(QString("Indexed %1 files.").arg(index.size())); emit q->statusInfo(QString("%1 files indexed.").arg(index.size())); } @@ -259,12 +259,12 @@ QFile file(QDir(QStandardPaths::writableLocation(QStandardPaths::DataLocation)). filePath(QString("%1.txt").arg(q->Core::Extension::id))); if (file.open(QIODevice::WriteOnly|QIODevice::Text)) { - qDebug() << qPrintable(QString("[%1] Serializing to %2").arg(q->Core::Extension::id, file.fileName())); + qDebug() << qPrintable(QString("Serializing files to '%1'").arg(file.fileName())); QTextStream out(&file); for (const shared_ptr &item : newIndex) out << item->path() << endl << item->mimetype().name() << endl; } else - qWarning() << qPrintable(QString("[%1] Could not write file %2: %3").arg(q->Core::Extension::id, file.fileName(), file.errorString())); + qWarning() << qPrintable(QString("Could not write to file '%1': %2").arg(file.fileName(), file.errorString())); return newIndex; } @@ -301,7 +301,7 @@ filePath(QString("%1.txt").arg(Core::Extension::id))); if (file.exists()) { if (file.open(QIODevice::ReadOnly| QIODevice::Text)) { - qDebug() << qPrintable(QString("[%1] Deserializing from %2").arg(Core::Extension::id, file.fileName())); + qDebug() << qPrintable(QString("Deserializing files from '%1'.").arg(file.fileName())); QTextStream in(&file); QMimeDatabase mimedatabase; while (!in.atEnd()) @@ -312,7 +312,7 @@ for (const auto &item : d->index) d->offlineIndex.add(item); } else - qWarning() << qPrintable(QString("[%1] Could not read from %2: %3").arg(Core::Extension::id, file.fileName(), file.errorString())); + qWarning() << qPrintable(QString("Could not read from file '%1': %2").arg(file.fileName(), file.errorString())); } // Index timer @@ -397,6 +397,31 @@ /** ***************************************************************************/ void Files::Extension::handleQuery(Core::Query * query) { + + if ( query->searchTerm().startsWith('/') || query->searchTerm().startsWith("~/") ) { + + QFileInfo fileInfo(query->searchTerm()); + + // Substitute tilde + if ( query->searchTerm()[0] == '~' ) + fileInfo.setFile(QDir::homePath()+query->searchTerm().right(query->searchTerm().size()-1)); + + // Get all matching files + QFileInfo pathInfo(fileInfo.path()); + if ( pathInfo.exists() && pathInfo.isDir() ) { + QMimeDatabase mimeDatabase; + QDirIterator dirIterator(pathInfo.filePath(), QDir::AllEntries|QDir::Hidden|QDir::NoDotAndDotDot); + while (dirIterator.hasNext()) { + dirIterator.next(); + if ( dirIterator.fileName().startsWith(fileInfo.fileName()) ) { + QMimeType mimetype = mimeDatabase.mimeTypeForFile(dirIterator.filePath()); + query->addMatch(std::make_shared(dirIterator.filePath(), mimetype), + static_cast(SHRT_MAX * static_cast(fileInfo.fileName().size()) / dirIterator.fileName().size())); + } + } + } + } + // Skip short terms since they pollute the output if ( query->searchTerm().size() < 3) return; diff -Nru albert-0.9.4/src/plugins/firefoxbookmarks/metadata.json albert-0.10.1/src/plugins/firefoxbookmarks/metadata.json --- albert-0.9.4/src/plugins/firefoxbookmarks/metadata.json 2017-03-01 10:22:31.000000000 +0000 +++ albert-0.10.1/src/plugins/firefoxbookmarks/metadata.json 2017-03-20 15:24:06.000000000 +0000 @@ -1,6 +1,6 @@ { "id" : "org.albert.extension.firefoxbookmarks", - "name" : "Firefox Bookmarks", + "name" : "Firefox bookmarks", "version" : "1.0", "platform" : "All", "group" : "Extensions", diff -Nru albert-0.9.4/src/plugins/firefoxbookmarks/src/main.cpp albert-0.10.1/src/plugins/firefoxbookmarks/src/main.cpp --- albert-0.9.4/src/plugins/firefoxbookmarks/src/main.cpp 2017-03-01 10:22:31.000000000 +0000 +++ albert-0.10.1/src/plugins/firefoxbookmarks/src/main.cpp 2017-03-20 15:24:06.000000000 +0000 @@ -109,7 +109,7 @@ futureWatcher.setFuture(QtConcurrent::run(this, &FirefoxBookmarksPrivate::indexFirefoxBookmarks)); // Notification - qDebug() << qPrintable(QString("[%1] Start indexing in background thread.").arg(q->Core::Extension::id)); + qDebug() << "Start indexing Firefox bookmarks."; emit q->statusInfo("Indexing bookmarks ..."); } @@ -126,7 +126,7 @@ offlineIndex.add(item); // Notification - qDebug() << qPrintable(QString("[%1] Indexing done (%2 items).").arg(q->Core::Extension::id).arg(index.size())); + qDebug() << qPrintable(QString("Indexed %1 Firefox bookmarks.").arg(index.size())); emit q->statusInfo(QString("%1 bookmarks indexed.").arg(index.size())); } @@ -139,7 +139,7 @@ QSqlDatabase database = QSqlDatabase::database(q->Core::Extension::id); if (!database.open()) { - qWarning() << qPrintable(QString("[%1] Could not open database: %2").arg(q->Core::Extension::id, database.databaseName())); + qWarning() << qPrintable(QString("Could not open Firefox database: %1").arg(database.databaseName())); return vector>(); } @@ -152,7 +152,7 @@ "FROM moz_bookmarks b " "JOIN moz_places p ON b.fk = p.id " // attach place (which has the url) "WHERE p.url NOT LIKE 'place%'") ) { // Those with place:... will not work with xdg-open - qWarning() << qPrintable(QString("[%1] Querying bookmarks failed: %2").arg(q->Core::Extension::id, result.lastError().text())); + qWarning() << qPrintable(QString("Querying Firefox bookmarks failed: %1").arg(result.lastError().text())); return vector>(); } @@ -195,7 +195,7 @@ }); shared_ptr actionFirefox = std::make_shared(); - actionFirefox->setText("Open URL in firefox"); + actionFirefox->setText("Open URL in Firefox"); actionFirefox->setAction([urlstr, this](){ QProcess::startDetached(firefoxExecutable, {urlstr}); }); @@ -236,14 +236,14 @@ // Add a sqlite database connection for this extension, check requirements QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE", Core::Extension::id); if ( !db.isValid() ) - throw QString("[%s] Firefox executable not found.").arg(Core::Extension::id); + throw "Firefox executable not found."; if (!db.driver()->hasFeature(QSqlDriver::Transactions)) - throw QString("[%s] Firefox executable not found.").arg(Core::Extension::id); + throw "Firefox executable not found."; // Find firefox executable d->firefoxExecutable = QStandardPaths::findExecutable("firefox"); if (d->firefoxExecutable.isEmpty()) - throw QString("[%s] Firefox executable not found.").arg(Core::Extension::id); + throw "Firefox executable not found."; // Locate profiles ini d->profilesIniPath = QStandardPaths::locate(QStandardPaths::HomeLocation, @@ -254,7 +254,7 @@ "Mozilla/firefox/profiles.ini", QStandardPaths::LocateFile); if (d->profilesIniPath.isEmpty()) - throw QString("[%1] Could not locate profiles.ini.").arg(Core::Extension::id); + throw "Could not locate profiles.ini."; // Load the settings QSettings s(qApp->applicationName()); @@ -271,7 +271,7 @@ QStringList ids = profilesIni.childGroups(); if ( ids.isEmpty() ) - qWarning() << qPrintable(QString("[%1] No Firefox profiles found.").arg(Core::Extension::id)); + qWarning() << "No Firefox profiles found."; else { // Use the last used profile @@ -340,7 +340,7 @@ cmb->addItem( QString("%1 (%2)").arg(profilesIni.value("Name").toString(), profileId), profileId); else { cmb->addItem(profileId, profileId); - qWarning() << qPrintable(QString("[%1] Profile '%2' does not contain a name.").arg(Core::Extension::id, profileId)); + qWarning() << qPrintable(QString("Firefox profile '%1' does not contain a name.").arg(profileId)); } // If the profileId match set the current item of the checkbox @@ -400,7 +400,7 @@ // Check if profile id is in profiles file if ( !profilesIni.childGroups().contains(d->currentProfileId) ){ - qWarning() << qPrintable(QString("[%1] Profile '%2' not found.").arg(Core::Extension::id, d->currentProfileId)); + qWarning() << qPrintable(QString("Firefox user profile '%2' not found.").arg(d->currentProfileId)); return; } @@ -409,7 +409,7 @@ // Check if the profile contains a path key if ( !profilesIni.contains("Path") ){ - qWarning() << qPrintable(QString("[%1] Profile '%2' does not contain a path.").arg(Core::Extension::id, d->currentProfileId)); + qWarning() << qPrintable(QString("Firefox profile '%2' does not contain a path.").arg(d->currentProfileId)); return; } diff -Nru albert-0.9.4/src/plugins/mpris/CMakeLists.txt albert-0.10.1/src/plugins/mpris/CMakeLists.txt --- albert-0.9.4/src/plugins/mpris/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 +++ albert-0.10.1/src/plugins/mpris/CMakeLists.txt 2017-03-20 15:24:06.000000000 +0000 @@ -0,0 +1,31 @@ +cmake_minimum_required(VERSION 2.8.11) + +PROJECT(mpris) + +FILE(GLOB_RECURSE SRC src/* metadata.json) + +find_package(Qt5 5.2.0 REQUIRED COMPONENTS + Widgets + DBus +) + +qt5_wrap_ui(UI + forms/configwidget.ui +) + +# Define the target +add_library(${PROJECT_NAME} SHARED ${SRC} ${UI}) + +# Set INCLUDE_DIRS and INTERFACE_INCLUDE_DIRS +target_include_directories(${PROJECT_NAME} PRIVATE src/) + +# Link target to libraries +target_link_libraries(${PROJECT_NAME} + ${Qt5Widgets_LIBRARIES} + ${Qt5DBus_LIBRARIES} + albertcore + xdg +) + +# Install target +install(TARGETS ${PROJECT_NAME} LIBRARY DESTINATION lib/albert/plugins) diff -Nru albert-0.9.4/src/plugins/mpris/forms/configwidget.ui albert-0.10.1/src/plugins/mpris/forms/configwidget.ui --- albert-0.9.4/src/plugins/mpris/forms/configwidget.ui 1970-01-01 00:00:00.000000000 +0000 +++ albert-0.10.1/src/plugins/mpris/forms/configwidget.ui 2017-03-20 15:24:06.000000000 +0000 @@ -0,0 +1,54 @@ + + + MPRIS::ConfigWidget + + + + 0 + 0 + 480 + 320 + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + <html><head/><body><p align="center"><span style=" color:#808080;">How to use MPRIS Control Center:</span></p><p align="center"><span style=" color:#808080;">If you have MPRIS-capable media players running (like Rhythmbox, VLC, ...) just type any of &quot;play&quot;, &quot;pause&quot;, &quot;stop&quot;, &quot;next&quot;, &quot;previous&quot; and you can send these commands directly to your player from albert.</span></p></body></html> + + + true + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + diff -Nru albert-0.9.4/src/plugins/mpris/metadata.json albert-0.10.1/src/plugins/mpris/metadata.json --- albert-0.9.4/src/plugins/mpris/metadata.json 1970-01-01 00:00:00.000000000 +0000 +++ albert-0.10.1/src/plugins/mpris/metadata.json 2017-03-20 15:24:06.000000000 +0000 @@ -0,0 +1,9 @@ +{ + "id" : "org.albert.extension.mpris", + "name" : "MPRIS Control", + "version" : "1.0", + "platform" : "Linux", + "group" : "Extensions", + "author" : "Martin Buergmann", + "dependencies" : ["dbus-daemon"] +} diff -Nru albert-0.9.4/src/plugins/mpris/mpris.qrc albert-0.10.1/src/plugins/mpris/mpris.qrc --- albert-0.9.4/src/plugins/mpris/mpris.qrc 1970-01-01 00:00:00.000000000 +0000 +++ albert-0.10.1/src/plugins/mpris/mpris.qrc 2017-03-20 15:24:06.000000000 +0000 @@ -0,0 +1,9 @@ + + + resources/1485099680_playback-play.svg + resources/1485099683_playback-fast-forward.svg + resources/1485099687_playback-rewind.svg + resources/1485099690_playback-pause.svg + resources/1485100510_primitive-square.svg + + diff -Nru albert-0.9.4/src/plugins/mpris/resources/1485099680_playback-play.svg albert-0.10.1/src/plugins/mpris/resources/1485099680_playback-play.svg --- albert-0.9.4/src/plugins/mpris/resources/1485099680_playback-play.svg 1970-01-01 00:00:00.000000000 +0000 +++ albert-0.10.1/src/plugins/mpris/resources/1485099680_playback-play.svg 2017-03-20 15:24:06.000000000 +0000 @@ -0,0 +1 @@ + \ No newline at end of file diff -Nru albert-0.9.4/src/plugins/mpris/resources/1485099683_playback-fast-forward.svg albert-0.10.1/src/plugins/mpris/resources/1485099683_playback-fast-forward.svg --- albert-0.9.4/src/plugins/mpris/resources/1485099683_playback-fast-forward.svg 1970-01-01 00:00:00.000000000 +0000 +++ albert-0.10.1/src/plugins/mpris/resources/1485099683_playback-fast-forward.svg 2017-03-20 15:24:06.000000000 +0000 @@ -0,0 +1 @@ + \ No newline at end of file diff -Nru albert-0.9.4/src/plugins/mpris/resources/1485099687_playback-rewind.svg albert-0.10.1/src/plugins/mpris/resources/1485099687_playback-rewind.svg --- albert-0.9.4/src/plugins/mpris/resources/1485099687_playback-rewind.svg 1970-01-01 00:00:00.000000000 +0000 +++ albert-0.10.1/src/plugins/mpris/resources/1485099687_playback-rewind.svg 2017-03-20 15:24:06.000000000 +0000 @@ -0,0 +1 @@ + \ No newline at end of file diff -Nru albert-0.9.4/src/plugins/mpris/resources/1485099690_playback-pause.svg albert-0.10.1/src/plugins/mpris/resources/1485099690_playback-pause.svg --- albert-0.9.4/src/plugins/mpris/resources/1485099690_playback-pause.svg 1970-01-01 00:00:00.000000000 +0000 +++ albert-0.10.1/src/plugins/mpris/resources/1485099690_playback-pause.svg 2017-03-20 15:24:06.000000000 +0000 @@ -0,0 +1 @@ + \ No newline at end of file diff -Nru albert-0.9.4/src/plugins/mpris/resources/1485100510_primitive-square.svg albert-0.10.1/src/plugins/mpris/resources/1485100510_primitive-square.svg --- albert-0.9.4/src/plugins/mpris/resources/1485100510_primitive-square.svg 1970-01-01 00:00:00.000000000 +0000 +++ albert-0.10.1/src/plugins/mpris/resources/1485100510_primitive-square.svg 2017-03-20 15:24:06.000000000 +0000 @@ -0,0 +1 @@ + \ No newline at end of file diff -Nru albert-0.9.4/src/plugins/mpris/src/command.cpp albert-0.10.1/src/plugins/mpris/src/command.cpp --- albert-0.9.4/src/plugins/mpris/src/command.cpp 1970-01-01 00:00:00.000000000 +0000 +++ albert-0.10.1/src/plugins/mpris/src/command.cpp 2017-03-20 15:24:06.000000000 +0000 @@ -0,0 +1,110 @@ +// albert extension mpris - a mpris interface plugin for albert +// Copyright (C) 2016 Martin Buergmann +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#include "command.h" +#include +#include +#include +#include +#include "item.h" + +/** ***************************************************************************/ +MPRIS::Command::Command(const QString &label, const QString &title, const QString &subtext, const QString &method, QString iconpath) + : label_(label), title_(title), subtext_(subtext), method_(method), iconpath_(iconpath) { +} + + + +/** ***************************************************************************/ +QString& MPRIS::Command::getIconPath() { + return iconpath_; +} + + + +/** ***************************************************************************/ +MPRIS::Command &MPRIS::Command::applicableWhen(const char* path, const char *property, const QVariant expectedValue, bool positivity) { + path_ = path; + property_ = property; + expectedValue_ = expectedValue; + positivity_ = positivity; + applicableCheck_ = true; + return *this; +} + + + +/** ***************************************************************************/ +SharedItem MPRIS::Command::produceAlbertItem(Player &player) const { + QDBusMessage msg = QDBusMessage::createMethodCall(player.getBusId(), "/org/mpris/MediaPlayer2", "org.mpris.MediaPlayer2.Player", method_); + SharedItem ptr(new MPRIS::Item(player, title_, subtext_, iconpath_, msg)); + return ptr; +} + + + +/** ***************************************************************************/ +bool MPRIS::Command::isApplicable(Player &p) const { + // Check the applicable-option if given + if (!applicableCheck_) + return true; + + // split DBus interface and property into seperate strings + int splitAt = property_.lastIndexOf('.'); + QString ifaceName = property_.left(splitAt); + QString propertyName = property_.right(property_.length() - splitAt -1); + + // Compose Get-Property-Message + QDBusMessage mesg = QDBusMessage::createMethodCall( + p.getBusId(), //"org.mpris.MediaPlayer2.rhythmbox", + path_, //"/org/mpris/MediaPlayer2", + "org.freedesktop.DBus.Properties", + "Get"); + QList args; + // Specify DBus interface to get the property from and the property-name + args.append(ifaceName); //"org.mpris.MediaPlayer2.Player"); + args.append(propertyName); //"CanGoNext"); + mesg.setArguments(args); + + // Query the property + QDBusMessage reply = QDBusConnection::sessionBus().call(mesg); + + // Check if the result is as expected + QVariant result = reply.arguments().at(0).value().variant(); + return (result == expectedValue_) == positivity_; +} + + + +/** ***************************************************************************/ +QString& MPRIS::Command::getLabel() { + return label_; +} + + + +/** ***************************************************************************/ +QString& MPRIS::Command::getMethod() { + return method_; +} + + + +/** ***************************************************************************/ +QString& MPRIS::Command::getTitle() { + return title_; +} + diff -Nru albert-0.9.4/src/plugins/mpris/src/command.h albert-0.10.1/src/plugins/mpris/src/command.h --- albert-0.9.4/src/plugins/mpris/src/command.h 1970-01-01 00:00:00.000000000 +0000 +++ albert-0.10.1/src/plugins/mpris/src/command.h 2017-03-20 15:24:06.000000000 +0000 @@ -0,0 +1,78 @@ +// albert extension mpris - a mpris interface plugin for albert +// Copyright (C) 2016 Martin Buergmann +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#pragma once + +#include +#include +#include +#include "query.h" +#include "player.h" +using std::function; +typedef std::shared_ptr SharedItem; + +namespace MPRIS { + +class Command +{ +public: + /** + * @brief Command Constructs a DBus command to launch from albert with the given parameters. + * @param label An internal variable to query at a later point. Not needed for the DBus query. + * @param title The title of the StandardItem which will be created. + * @param subtext The subtext of the StandardItem which will be created. + * @param method The DBus method to invoke when this command is performed. + * @param iconpath The path to the icon which the StandardItem will get. + */ + Command(const QString& label, const QString& title, const QString& subtext, const QString& method, QString iconpath); + + QString& getLabel(); + QString& getTitle(); + QString& getMethod(); + QString& getIconPath(); + + /** + * @brief applicableWhen Configure this command to be only appicable under a certian (given) conditions. + * @param path The path to query the property from. + * @param property The name of the property. This property will be checked as condition. + * @param expectedValue The value of the property. + * @param positivity The result of the equality-check (queriedValue == expectedValue). Here you can negate the result. + * @return Returns itself, but now configured for applicability-check + */ + Command& applicableWhen(const char *path, const char* property, const QVariant expectedValue, bool positivity); + + /** + * @brief produceStandardItem Produces an instance of AlbertItem for this command to invoke on a given Player. + * @return Returns a shared_ptr on this AlbertItem. + */ + SharedItem produceAlbertItem(Player &) const; + + /** + * @brief isApplicable If configured, checks if the given property meets the expected criteria. + * @return True if not configured or match, false if the property is different than expected. + */ + bool isApplicable(Player&) const; + +private: + QString label_, title_, subtext_, method_, iconpath_; + bool applicableCheck_; + QString path_; + QString property_; + QVariant expectedValue_; + bool positivity_; +}; + +} // namespace MPRIS diff -Nru albert-0.9.4/src/plugins/mpris/src/configwidget.cpp albert-0.10.1/src/plugins/mpris/src/configwidget.cpp --- albert-0.9.4/src/plugins/mpris/src/configwidget.cpp 1970-01-01 00:00:00.000000000 +0000 +++ albert-0.10.1/src/plugins/mpris/src/configwidget.cpp 2017-03-20 15:24:06.000000000 +0000 @@ -0,0 +1,29 @@ +// albert extension mpris - a mpris interface plugin for albert +// Copyright (C) 2016 Martin Buergmann +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#include "configwidget.h" + +/** ***************************************************************************/ +MPRIS::ConfigWidget::ConfigWidget(QWidget *parent) : QWidget(parent) { + ui.setupUi(this); +} + + + +/** ***************************************************************************/ +MPRIS::ConfigWidget::~ConfigWidget() { + +} diff -Nru albert-0.9.4/src/plugins/mpris/src/configwidget.h albert-0.10.1/src/plugins/mpris/src/configwidget.h --- albert-0.9.4/src/plugins/mpris/src/configwidget.h 1970-01-01 00:00:00.000000000 +0000 +++ albert-0.10.1/src/plugins/mpris/src/configwidget.h 2017-03-20 15:24:06.000000000 +0000 @@ -0,0 +1,30 @@ +// albert extension mpris - a mpris interface plugin for albert +// Copyright (C) 2016 Martin Buergmann +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#pragma once +#include +#include "ui_configwidget.h" + +namespace MPRIS { +class ConfigWidget final : public QWidget +{ + Q_OBJECT +public: + explicit ConfigWidget(QWidget *parent = 0); + ~ConfigWidget(); + Ui::ConfigWidget ui; +}; +} diff -Nru albert-0.9.4/src/plugins/mpris/src/item.cpp albert-0.10.1/src/plugins/mpris/src/item.cpp --- albert-0.9.4/src/plugins/mpris/src/item.cpp 1970-01-01 00:00:00.000000000 +0000 +++ albert-0.10.1/src/plugins/mpris/src/item.cpp 2017-03-20 15:24:06.000000000 +0000 @@ -0,0 +1,65 @@ +// albert extension mpris - a mpris interface plugin for albert +// Copyright (C) 2016 Martin Buergmann +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#include "item.h" +#include "standardaction.h" +using Core::StandardAction; +#include + + +/** ***************************************************************************/ +MPRIS::Item::Item(Player &p, const QString &title, const QString &subtext, const QString &iconPath, const QDBusMessage &msg) + : iconPath_(iconPath), message_(msg) { + if (title.contains("%1")) + text_ = title.arg(p.getName()); + else + text_ = title; + if (subtext.contains("%1")) + subtext_ = subtext.arg(p.getName()); + else + subtext_ = subtext; + actions_.push_back(shared_ptr(new StandardAction(subtext_, [this](){ + QDBusConnection::sessionBus().send(message_); +// flags->hideWidget = hideAfter_; +// flags->clearInput = hideAfter_; + }))); + if (p.canRaise()) { + actions_.push_back(shared_ptr(new StandardAction("Raise Window", [&p](){ + QString busid = p.getBusId(); + QDBusMessage raise = QDBusMessage::createMethodCall(busid, "/org/mpris/MediaPlayer2", "org.mpris.MediaPlayer2", "Raise"); + if (!QDBusConnection::sessionBus().send(raise)) { + qWarning("Error calling raise method on dbus://%s", busid.toStdString().c_str()); + } + }))); + } + id_ = "extension.mpris.item:%1.%2"; + id_ = id_.arg(p.getBusId()).arg(msg.member()); +} + + + +/** ***************************************************************************/ +MPRIS::Item::~Item() { + +} + + + +/** ***************************************************************************/ +vector> MPRIS::Item::actions() { + return actions_; +} + diff -Nru albert-0.9.4/src/plugins/mpris/src/item.h albert-0.10.1/src/plugins/mpris/src/item.h --- albert-0.9.4/src/plugins/mpris/src/item.h 1970-01-01 00:00:00.000000000 +0000 +++ albert-0.10.1/src/plugins/mpris/src/item.h 2017-03-20 15:24:06.000000000 +0000 @@ -0,0 +1,48 @@ +// albert extension mpris - a mpris interface plugin for albert +// Copyright (C) 2016 Martin Buergmann +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#pragma once +#include +#include +using std::vector; +#include "standarditem.h" +#include "player.h" +#include +using std::shared_ptr; +using Core::Action; + +namespace MPRIS { +class Item final : public Core::Item +{ +public: + Item(Player &p, const QString& title, const QString& subtext, const QString& iconPath, const QDBusMessage& msg); + ~Item(); + + QString id() const override { return id_; } + QString text() const override { return text_; } + QString subtext() const override { return subtext_; } + QString iconPath() const override { return iconPath_; } + vector> actions() override; + +private: + QString id_; + QString text_; + QString subtext_; + QString iconPath_; + QDBusMessage message_; + vector> actions_; +}; +} diff -Nru albert-0.9.4/src/plugins/mpris/src/main.cpp albert-0.10.1/src/plugins/mpris/src/main.cpp --- albert-0.9.4/src/plugins/mpris/src/main.cpp 1970-01-01 00:00:00.000000000 +0000 +++ albert-0.10.1/src/plugins/mpris/src/main.cpp 2017-03-20 15:24:06.000000000 +0000 @@ -0,0 +1,242 @@ +// albert extension mpris - a mpris interface plugin for albert +// Copyright (C) 2016 Martin Buergmann +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#include +#include +#include "main.h" +#include "configwidget.h" +#include "query.h" +#include "xdgiconlookup.h" +#include "command.h" + +#define themeOr(name, fallbk) XdgIconLookup::iconPath(name).isEmpty() ? fallbk : XdgIconLookup::iconPath(name) + + + +/** ***************************************************************************/ +class MPRIS::MPRISPrivate { +public: + ~MPRISPrivate() { + // If there are still media player objects, delete them + qDeleteAll(mediaPlayers); + // Don't need to destruct the command objects. + // This is done by the destructor of QMap + } + + + const char* name = "MPRIS Control"; + static QDBusMessage findPlayerMsg; + QPointer widget; + QList mediaPlayers; + QStringList commands; + QMap commandObjects; +}; + + + +QDBusMessage MPRIS::MPRISPrivate::findPlayerMsg = QDBusMessage::createMethodCall("org.freedesktop.DBus", "/", "org.freedesktop.DBus", "ListNames"); + + + +/** ***************************************************************************/ +/** ***************************************************************************/ +/** ***************************************************************************/ +MPRIS::Extension::Extension() + : Core::Extension("org.albert.extension.mpris"), + Core::QueryHandler(Core::Extension::id), + d(new MPRIS::MPRISPrivate) { + qDebug("[%s] Initialize extension", d->name); + + QString icon; + + // Setup the DBus commands + icon = themeOr("media-playback-start", ":play"); + Command* nextToAdd = new Command( + "play", // Label + "Start playing", // Title + "Start playing on %1", // Subtext + "Play", // DBus Method + icon + ); + nextToAdd->applicableWhen("/org/mpris/MediaPlayer2", "org.mpris.MediaPlayer2.Player.PlaybackStatus", "Playing", false); + d->commands.append("play"); + d->commandObjects.insert("play", *nextToAdd); + + icon = themeOr("media-playback-pause", ":pause"); + nextToAdd = new Command( + "pause", + "Pause", + "Pause %1", + "Pause", + icon + ); + nextToAdd->applicableWhen("/org/mpris/MediaPlayer2", "org.mpris.MediaPlayer2.Player.PlaybackStatus", "Playing", true); + d->commands.append("pause"); + d->commandObjects.insert("pause", *nextToAdd); + + icon = themeOr("media-playback-stop", ":stop"); + nextToAdd = new Command( + "stop", + "Stop playing", + "Stop %1", + "Stop", + icon + ); + nextToAdd->applicableWhen("/org/mpris/MediaPlayer2", "org.mpris.MediaPlayer2.Player.PlaybackStatus", "Playing", true); + d->commands.append("stop"); + d->commandObjects.insert("stop", *nextToAdd); + + icon = themeOr("media-skip-forward", ":next"); + nextToAdd = new Command( + "next", + "Next track", + "Play next track on %1", + "Next", + icon + ); + nextToAdd->applicableWhen("/org/mpris/MediaPlayer2", "org.mpris.MediaPlayer2.Player.CanGoNext", true, true); + //.fireCallback([](){qDebug("NEXT");}) + d->commands.append("next"); + d->commandObjects.insert("next", *nextToAdd); + + icon = themeOr("media-skip-backward", ":prev"); + nextToAdd = new Command( + "previous", + "Previous track", + "Play previous track on %1", + "Previous", + icon + ); + nextToAdd->applicableWhen("/org/mpris/MediaPlayer2", "org.mpris.MediaPlayer2.Player.CanGoPrevious", true, true); + d->commands.append("previous"); + d->commandObjects.insert("previous", *nextToAdd); + + qDebug("[%s] Extension initialized", d->name); +} + + + +/** ***************************************************************************/ +MPRIS::Extension::~Extension() { + +} + + + +/** ***************************************************************************/ +QWidget *MPRIS::Extension::widget(QWidget *parent) { + if (d->widget.isNull()) { + d->widget = new ConfigWidget(parent); + } + return d->widget; +} + + + +/** ***************************************************************************/ +void MPRIS::Extension::setupSession() { + + // Clean the memory + qDeleteAll(d->mediaPlayers); + d->mediaPlayers.clear(); + + // If there is no session bus, abort + if (!QDBusConnection::sessionBus().isConnected()) + return; + + // Querying the DBus to list all available services + QDBusMessage response = QDBusConnection::sessionBus().call(MPRISPrivate::findPlayerMsg); + + // Do some error checking + if (response.type() == QDBusMessage::ReplyMessage) { + QList args = response.arguments(); + if (args.length() == 1) { + QVariant arg = args.at(0); + if (!arg.isNull() && arg.isValid()) { + QStringList runningBusEndpoints = arg.toStringList(); + if (!runningBusEndpoints.isEmpty()) { + // No errors + + // Filter all mpris capable + //names = names.filter(filterRegex); + QStringList busids; + for (QString& id: runningBusEndpoints) { + if (id.startsWith("org.mpris.MediaPlayer2.")) + busids.append(id); + } + + for (QString& busid : busids) { + // And add their player object to the list + d->mediaPlayers.append(new Player(busid)); + } + + + } else { + qCritical("[%s] DBus error: Argument is either not type of QStringList or is empty!", d->name); + } + } else { + qCritical("[%s] DBus error: Reply argument not valid or null!", d->name); + } + } else { + qCritical("[%s] DBus error: Expected 1 argument for DBus reply. Got %d", d->name, args.length()); + } + } else { + qCritical("[%s] DBus error: %s", d->name, response.errorMessage().toStdString().c_str()); + } +} + + + +/** ***************************************************************************/ +void MPRIS::Extension::handleQuery(Query *query) { + // Do not proceed if there are no players running. Why would you even? + if (d->mediaPlayers.isEmpty()) + return; + + const QString& q = query->searchTerm().toLower(); + + // Filter applicable commands + QStringList cmds; + for (QString& cmd : d->commands) { + if (cmd.startsWith(q)) + cmds.append(cmd); + } + + + // For every option create entries for every player + short percentage = 0; + for (QString& cmd: cmds) { + // Calculate how many percent of the query match the command + percentage = (float)q.length() / (float)cmd.length() *100; + + // Get the command + Command& toExec = d->commandObjects.find(cmd).value(); + // For every player: + for (Player* p: d->mediaPlayers) { + // See if it's applicable for this player + if (toExec.isApplicable(*p)) + // And add a match if so + query->addMatch(toExec.produceAlbertItem(*p), percentage); + } + } +} + + + +/** ***************************************************************************/ +QString MPRIS::Extension::name() const { + return d->name; +} diff -Nru albert-0.9.4/src/plugins/mpris/src/main.h albert-0.10.1/src/plugins/mpris/src/main.h --- albert-0.9.4/src/plugins/mpris/src/main.h 1970-01-01 00:00:00.000000000 +0000 +++ albert-0.10.1/src/plugins/mpris/src/main.h 2017-03-20 15:24:06.000000000 +0000 @@ -0,0 +1,65 @@ +// albert extension mpris - a mpris interface plugin for albert +// Copyright (C) 2016 Martin Buergmann +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#pragma once +#include +#include +#include "player.h" +#include "command.h" +#include "extension.h" +#include "queryhandler.h" +#include +using Core::Query; + +class QDBusMessage; + +namespace MPRIS { + +class MPRISPrivate; +class ConfigWidget; + +class Extension final : + public QObject, + public Core::Extension, + public Core::QueryHandler +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID ALBERT_EXTENSION_IID FILE "metadata.json") + +public: + Extension(); + ~Extension(); + + /* + * Implementation of extension interface + */ + + QWidget *widget(QWidget *parent = nullptr) override; + void setupSession() override; + void handleQuery(Query *query) override; + QString name() const override; + + + /* + * Extension specific members + */ + +private: + + std::unique_ptr d; + +}; +} diff -Nru albert-0.9.4/src/plugins/mpris/src/player.cpp albert-0.10.1/src/plugins/mpris/src/player.cpp --- albert-0.9.4/src/plugins/mpris/src/player.cpp 1970-01-01 00:00:00.000000000 +0000 +++ albert-0.10.1/src/plugins/mpris/src/player.cpp 2017-03-20 15:24:06.000000000 +0000 @@ -0,0 +1,39 @@ +// albert extension mpris - a mpris interface plugin for albert +// Copyright (C) 2016 Martin Buergmann +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#include "player.h" +#include +#include + +/** ***************************************************************************/ +MPRIS::Player::Player(QString &busid) : busid_(busid), name_(busid) { + // Query the name of the media player of which we have the bus id. + QDBusInterface iface(busid, "/org/mpris/MediaPlayer2", "org.mpris.MediaPlayer2"); + + QVariant prop = iface.property("Identity"); + if (prop.isValid() && !prop.isNull() && prop.canConvert(QVariant::String)) { + name_ = prop.toString(); + } else { + qWarning("DBus: Name is either invalid, null or not instanceof string"); + } + + prop = iface.property("CanRaise"); + if (prop.isValid() && !prop.isNull() && prop.canConvert(QVariant::Bool)) { + canRaise_ = prop.toBool(); + } else { + qWarning("DBus: CanRaise is either invalid, null or not instanceof bool"); + } +} diff -Nru albert-0.9.4/src/plugins/mpris/src/player.h albert-0.10.1/src/plugins/mpris/src/player.h --- albert-0.9.4/src/plugins/mpris/src/player.h 1970-01-01 00:00:00.000000000 +0000 +++ albert-0.10.1/src/plugins/mpris/src/player.h 2017-03-20 15:24:06.000000000 +0000 @@ -0,0 +1,37 @@ +// albert extension mpris - a mpris interface plugin for albert +// Copyright (C) 2016 Martin Buergmann +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#pragma once + +#include + +namespace MPRIS { + +class Player +{ +public: + Player(QString& busid); + const QString& getName() const { return name_; } + const QString& getBusId() const { return busid_; } + bool canRaise() const { return canRaise_; } + +private: + QString busid_, name_; + bool canRaise_; +}; + +} // namespace MPRIS + diff -Nru albert-0.9.4/src/plugins/ssh/CMakeLists.txt albert-0.10.1/src/plugins/ssh/CMakeLists.txt --- albert-0.9.4/src/plugins/ssh/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 +++ albert-0.10.1/src/plugins/ssh/CMakeLists.txt 2017-03-20 15:24:06.000000000 +0000 @@ -0,0 +1,33 @@ +cmake_minimum_required(VERSION 2.8.12) + +PROJECT(ssh) + +FILE(GLOB_RECURSE SRC src/* metadata.json) + +find_package(Qt5 5.2.0 REQUIRED COMPONENTS + Widgets +) + +qt5_wrap_ui(UI + configwidget.ui +) + +qt5_add_resources(QRC + ${PROJECT_NAME}.qrc +) + +# Define the target +add_library(${PROJECT_NAME} SHARED ${SRC} ${UI} ${QRC}) + +# Set INCLUDE_DIRS and INTERFACE_INCLUDE_DIRS +target_include_directories(${PROJECT_NAME} PRIVATE src/) + +# Link target to libraries +target_link_libraries(${PROJECT_NAME} + ${Qt5Widgets_LIBRARIES} + albertcore + xdg +) + +# Install target +install(TARGETS ${PROJECT_NAME} LIBRARY DESTINATION lib/albert/plugins) diff -Nru albert-0.9.4/src/plugins/ssh/configwidget.ui albert-0.10.1/src/plugins/ssh/configwidget.ui --- albert-0.9.4/src/plugins/ssh/configwidget.ui 1970-01-01 00:00:00.000000000 +0000 +++ albert-0.10.1/src/plugins/ssh/configwidget.ui 2017-03-20 15:24:06.000000000 +0000 @@ -0,0 +1,66 @@ + + + Ssh::ConfigWidget + + + + 0 + 0 + 480 + 320 + + + + + + + <html> +<head/> +<body> +<p>This extension scans your /etc/ssh/config and ~/.ssh/config<br>and makes your ssh hosts accessible by Albert.</p> +</body> +</html> + + + true + + + + + + + Use 'known_hosts' + + + + + + + + 0 + 0 + + + + Rescan + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + diff -Nru albert-0.9.4/src/plugins/ssh/metadata.json albert-0.10.1/src/plugins/ssh/metadata.json --- albert-0.9.4/src/plugins/ssh/metadata.json 1970-01-01 00:00:00.000000000 +0000 +++ albert-0.10.1/src/plugins/ssh/metadata.json 2017-03-20 15:24:06.000000000 +0000 @@ -0,0 +1,10 @@ +{ + "id" : "org.albert.extension.ssh", + "name" : "Secure Shell", + "version" : "1.0", + "platform" : "All", + "group" : "Extensions", + "author" : "Manuel Schneider", + "dependencies" : [], + "enabledbydefault": true +} diff -Nru albert-0.9.4/src/plugins/ssh/resources/ssh.svg albert-0.10.1/src/plugins/ssh/resources/ssh.svg --- albert-0.9.4/src/plugins/ssh/resources/ssh.svg 1970-01-01 00:00:00.000000000 +0000 +++ albert-0.10.1/src/plugins/ssh/resources/ssh.svg 2017-03-20 15:24:06.000000000 +0000 @@ -0,0 +1,741 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -Nru albert-0.9.4/src/plugins/ssh/src/configwidget.cpp albert-0.10.1/src/plugins/ssh/src/configwidget.cpp --- albert-0.9.4/src/plugins/ssh/src/configwidget.cpp 1970-01-01 00:00:00.000000000 +0000 +++ albert-0.10.1/src/plugins/ssh/src/configwidget.cpp 2017-03-20 15:24:06.000000000 +0000 @@ -0,0 +1,29 @@ +// albert - a simple application launcher for linux +// Copyright (C) 2014-2015 Manuel Schneider +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#include "configwidget.h" + +/** ***************************************************************************/ +Ssh::ConfigWidget::ConfigWidget(QWidget *parent) : QWidget(parent) { + ui.setupUi(this); +} + + + +/** ***************************************************************************/ +Ssh::ConfigWidget::~ConfigWidget() { + +} diff -Nru albert-0.9.4/src/plugins/ssh/src/configwidget.h albert-0.10.1/src/plugins/ssh/src/configwidget.h --- albert-0.9.4/src/plugins/ssh/src/configwidget.h 1970-01-01 00:00:00.000000000 +0000 +++ albert-0.10.1/src/plugins/ssh/src/configwidget.h 2017-03-20 15:24:06.000000000 +0000 @@ -0,0 +1,32 @@ +// albert - a simple application launcher for linux +// Copyright (C) 2014-2015 Manuel Schneider +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#pragma once +#include +#include "ui_configwidget.h" + +namespace Ssh { + +class ConfigWidget final : public QWidget +{ + Q_OBJECT +public: + explicit ConfigWidget(QWidget *parent = 0); + ~ConfigWidget(); + Ui::ConfigWidget ui; +}; + +} diff -Nru albert-0.9.4/src/plugins/ssh/src/main.cpp albert-0.10.1/src/plugins/ssh/src/main.cpp --- albert-0.9.4/src/plugins/ssh/src/main.cpp 1970-01-01 00:00:00.000000000 +0000 +++ albert-0.10.1/src/plugins/ssh/src/main.cpp 2017-03-20 15:24:06.000000000 +0000 @@ -0,0 +1,253 @@ +// albert - a simple application launcher for linux +// Copyright (C) 2014-2015 Manuel Schneider +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "configwidget.h" +#include "standardaction.h" +#include "standarditem.h" +#include "main.h" +#include "query.h" +#include "xdgiconlookup.h" +using std::shared_ptr; +using std::vector; +using namespace Core; + +extern QString terminalCommand; + +namespace { + +const char* CFG_USE_KNOWN_HOSTS = "use_known_hosts"; +const bool DEF_USE_KNOWN_HOSTS = true; + +// Function to extract the hosts of a ssh config file +std::set getSshHostsFromConfig(const QString& path) { + std::set hosts; + QFile file(path); + if (file.open(QIODevice::ReadOnly | QIODevice::Text)) { + QTextStream in(&file); + while ( !in.atEnd() ) { + QStringList fields = in.readLine().split(QRegularExpression("\\s+"), QString::SkipEmptyParts); + if ( fields.size() > 1 && fields[0] == "Host") + for ( int i = 1; i < fields.size(); ++i ){ + if ( !(fields[i].contains('*') || fields[i].contains('?')) ) + hosts.insert(fields[i]); + } + } + file.close(); + } + return hosts; +} + +// Function to extract the hosts of a ssh known_hosts file +std::set getSshHostsFromKnownHosts(const QString& path) { + std::set hosts; + QFile file(path); + if ( file.open(QIODevice::ReadOnly | QIODevice::Text) ) { + QRegularExpression re ("^[a-zA-Z0-9\\.]*(?=(,.*)*\\s)"); + QTextStream in(&file); + while ( !in.atEnd() ) { + QString line = in.readLine(); + QRegularExpressionMatch match = re.match(line); + if ( match.hasMatch() ) + hosts.insert(match.captured(0)); + } + file.close(); + } + return hosts; +} + +} + + + +class Ssh::SshPrivate +{ +public: + QString icon; + QPointer widget; + QFileSystemWatcher fileSystemWatcher; + vector> hosts; + bool useKnownHosts; +}; + + +/** ***************************************************************************/ +/** ***************************************************************************/ +/** ***************************************************************************/ +/** ***************************************************************************/ +Ssh::Extension::Extension() + : Core::Extension("org.albert.extension.ssh"), + Core::QueryHandler(Core::Extension::id), + d(new SshPrivate) { + + // Load settings + QSettings s(qApp->applicationName()); + s.beginGroup(Core::Extension::id); + d->useKnownHosts = s.value(CFG_USE_KNOWN_HOSTS, DEF_USE_KNOWN_HOSTS).toBool(); + s.endGroup(); + + // Find ssh + if (QStandardPaths::findExecutable("ssh").isNull()) + throw QString("[%s] ssh not found.").arg(Core::Extension::id); + + // Find an appropriate icon + d->icon = XdgIconLookup::iconPath("ssh"); + if (d->icon.isEmpty()) + d->icon = XdgIconLookup::iconPath("terminal"); + if (d->icon.isEmpty()) + d->icon = ":ssh"; // Fallback + + rescan(); +} + + + +/** ***************************************************************************/ +Ssh::Extension::~Extension() { + +} + + +/** ***************************************************************************/ +QString Ssh::Extension::trigger() const { + return "ssh"; +} + + + +/** ***************************************************************************/ +QWidget *Ssh::Extension::widget(QWidget *parent) { + if (d->widget.isNull()) { + d->widget = new ConfigWidget(parent); + + // Checkboxes + d->widget->ui.checkBox_knownhosts->setChecked(useKnownHosts()); + connect(d->widget->ui.checkBox_knownhosts, &QCheckBox::toggled, + this, &Extension::setUseKnownHosts); + + connect(d->widget->ui.pushButton_rescan, &QPushButton::clicked, + this, &Extension::rescan); + + } + return d->widget; +} + + + +/** ***************************************************************************/ +void Ssh::Extension::handleQuery(Core::Query * query) { + QStringList queryTerms = query->searchTerm().split(' ',QString::SkipEmptyParts); + + // Add all hosts if there are no arguments + if ( queryTerms.size() == 1) + for ( shared_ptr& host : d->hosts ) + query->addMatch(host, 1); + + if ( queryTerms.size() != 2) + return; + + // Add all hosts that the query is a prefix of + for ( shared_ptr& host : d->hosts ) + if ( host->text().startsWith(queryTerms[1]) ) + query->addMatch(host, SHRT_MAX * static_cast(query->searchTerm().size())/host->text().size()); + + // Add the quick connect item + std::shared_ptr item = std::make_shared(""); + item->setText(queryTerms[1]); + item->setSubtext(QString("Connect to '%1' using ssh").arg(queryTerms[1])); + item->setCompletionString(QString("ssh %1").arg(queryTerms[1])); + item->setIconPath(d->icon); + + shared_ptr action = std::make_shared(); + action->setText(QString("Connect to '%1' using ssh").arg(queryTerms[1])); + action->setAction([queryTerms](){ + QProcess::startDetached(QString("%1 \"ssh %2\"").arg(terminalCommand, queryTerms[1])); + }); + item->setActions({action}); + + query->addMatch(item, 0); +} + + + +/** ***************************************************************************/ +void Ssh::Extension::rescan() { + + // Build a new index + vector> sshHosts; + + // Get the hosts in config + std::set hosts; + for ( const QString& path : {QString("/etc/ssh/config"), QDir::home().filePath(".ssh/config")} ) + if ( QFile::exists(path) ) + for ( const QString& host : getSshHostsFromConfig(path) ) + hosts.insert(host); + + // Get the hosts in known_hosts + if ( d->useKnownHosts ) { + const QString& path = QDir::home().filePath(".ssh/known_hosts"); + if ( QFile::exists(path) ) + for ( const QString& host : getSshHostsFromKnownHosts(path) ) + hosts.insert(host); + } + + + for ( const QString& host : hosts ){ + + // Create item + std::shared_ptr si = std::make_shared(host); + si->setText(host); + si->setSubtext(QString("Connect to '%1' using ssh").arg(host)); + si->setCompletionString(QString("ssh %1").arg(host)); + si->setIconPath(d->icon); + + shared_ptr sa = std::make_shared(); + sa->setText(QString("Connect to '%1' using ssh").arg(host)); + sa->setAction([host](){ + QProcess::startDetached(QString("%1 \"ssh %2\"").arg(terminalCommand, host)); + }); + si->setActions({sa}); + + sshHosts.push_back(std::move(si)); + } + + d->hosts = std::move(sshHosts); +} + + + +/** ***************************************************************************/ +bool Ssh::Extension::useKnownHosts() { + return d->useKnownHosts; +} + + + +/** ***************************************************************************/ +void Ssh::Extension::setUseKnownHosts(bool b) { + QSettings(qApp->applicationName()).setValue(QString("%1/%2").arg(Core::Extension::id, CFG_USE_KNOWN_HOSTS), b); + d->useKnownHosts = b; + rescan(); +} diff -Nru albert-0.9.4/src/plugins/ssh/src/main.h albert-0.10.1/src/plugins/ssh/src/main.h --- albert-0.9.4/src/plugins/ssh/src/main.h 1970-01-01 00:00:00.000000000 +0000 +++ albert-0.10.1/src/plugins/ssh/src/main.h 2017-03-20 15:24:06.000000000 +0000 @@ -0,0 +1,64 @@ +// albert - a simple application launcher for linux +// Copyright (C) 2014-2015 Manuel Schneider +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#pragma once +#include +#include +#include "extension.h" +#include "queryhandler.h" + +namespace Ssh { + +class SshPrivate; +class ConfigWidget; + +class Extension final : + public QObject, + public Core::Extension, + public Core::QueryHandler +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID ALBERT_EXTENSION_IID FILE "metadata.json") + +public: + + Extension(); + ~Extension(); + + /* + * Implementation of extension interface + */ + + QString name() const override { return "SecureShell"; } + QString trigger() const override; + QWidget *widget(QWidget *parent = nullptr) override; + void handleQuery(Core::Query * query) override; + + /* + * Extension specific members + */ + + void rescan(); + + bool useKnownHosts(); + void setUseKnownHosts(bool b = true); + +private: + + std::unique_ptr d; + +}; +} diff -Nru albert-0.9.4/src/plugins/ssh/ssh.qrc albert-0.10.1/src/plugins/ssh/ssh.qrc --- albert-0.9.4/src/plugins/ssh/ssh.qrc 1970-01-01 00:00:00.000000000 +0000 +++ albert-0.10.1/src/plugins/ssh/ssh.qrc 2017-03-20 15:24:06.000000000 +0000 @@ -0,0 +1,5 @@ + + + resources/ssh.svg + + diff -Nru albert-0.9.4/src/plugins/templateExtension/CMakeLists.txt albert-0.10.1/src/plugins/templateExtension/CMakeLists.txt --- albert-0.9.4/src/plugins/templateExtension/CMakeLists.txt 2017-03-01 10:22:31.000000000 +0000 +++ albert-0.10.1/src/plugins/templateExtension/CMakeLists.txt 2017-03-20 15:24:06.000000000 +0000 @@ -1,10 +1,12 @@ cmake_minimum_required(VERSION 2.8.12) -PROJECT(template) +PROJECT(projectid) FILE(GLOB_RECURSE SRC src/* metadata.json) -find_package(Qt5Widgets 5.2 REQUIRED) +find_package(Qt5 5.2.0 REQUIRED COMPONENTS + Widgets +) set(LIB ${Qt5Widgets_LIBRARIES} diff -Nru albert-0.9.4/src/plugins/templateExtension/configwidget.ui albert-0.10.1/src/plugins/templateExtension/configwidget.ui --- albert-0.9.4/src/plugins/templateExtension/configwidget.ui 2017-03-01 10:22:31.000000000 +0000 +++ albert-0.10.1/src/plugins/templateExtension/configwidget.ui 2017-03-20 15:24:06.000000000 +0000 @@ -1,7 +1,7 @@ - Template::ConfigWidget - + ProjectNamespace::ConfigWidget + 0 diff -Nru albert-0.9.4/src/plugins/templateExtension/metadata.json albert-0.10.1/src/plugins/templateExtension/metadata.json --- albert-0.9.4/src/plugins/templateExtension/metadata.json 2017-03-01 10:22:31.000000000 +0000 +++ albert-0.10.1/src/plugins/templateExtension/metadata.json 2017-03-20 15:24:06.000000000 +0000 @@ -1,10 +1,10 @@ { - "id" : "org.albert.extension.template", + "id" : "org.albert.extension.projectid", "name" : "Template", "version" : "1.0", "platform" : "All", "group" : "Extensions", - "author" : "Manuel Schneider", + "author" : "Author missing", "dependencies" : [], - "enabledbydefault": false + "enabledbydefault": false } diff -Nru albert-0.9.4/src/plugins/templateExtension/src/configwidget.cpp albert-0.10.1/src/plugins/templateExtension/src/configwidget.cpp --- albert-0.9.4/src/plugins/templateExtension/src/configwidget.cpp 2017-03-01 10:22:31.000000000 +0000 +++ albert-0.10.1/src/plugins/templateExtension/src/configwidget.cpp 2017-03-20 15:24:06.000000000 +0000 @@ -17,13 +17,13 @@ #include "configwidget.h" /** ***************************************************************************/ -Template::ConfigWidget::ConfigWidget(QWidget *parent) : QWidget(parent) { +ProjectNamespace::ConfigWidget::ConfigWidget(QWidget *parent) : QWidget(parent) { ui.setupUi(this); } /** ***************************************************************************/ -Template::ConfigWidget::~ConfigWidget() { +ProjectNamespace::ConfigWidget::~ConfigWidget() { } diff -Nru albert-0.9.4/src/plugins/templateExtension/src/configwidget.h albert-0.10.1/src/plugins/templateExtension/src/configwidget.h --- albert-0.9.4/src/plugins/templateExtension/src/configwidget.h 2017-03-01 10:22:31.000000000 +0000 +++ albert-0.10.1/src/plugins/templateExtension/src/configwidget.h 2017-03-20 15:24:06.000000000 +0000 @@ -18,7 +18,7 @@ #include #include "ui_configwidget.h" -namespace Template { +namespace ProjectNamespace { class ConfigWidget final : public QWidget { Q_OBJECT diff -Nru albert-0.9.4/src/plugins/templateExtension/src/main.cpp albert-0.10.1/src/plugins/templateExtension/src/main.cpp --- albert-0.9.4/src/plugins/templateExtension/src/main.cpp 2017-03-01 10:22:31.000000000 +0000 +++ albert-0.10.1/src/plugins/templateExtension/src/main.cpp 2017-03-20 15:24:06.000000000 +0000 @@ -24,7 +24,7 @@ -class Template::TemplatePrivate +class ProjectNamespace::ProjectNamespacePrivate { public: QPointer widget; @@ -33,10 +33,10 @@ /** ***************************************************************************/ -Template::Extension::Extension() - : Core::Extension("org.albert.extension.template"), +ProjectNamespace::Extension::Extension() + : Core::Extension("org.albert.extension.projectid"), Core::QueryHandler(Core::Extension::id), - d(new TemplatePrivate) { + d(new ProjectNamespacePrivate) { // You can throw in the constructor if something fatal happened throw std::runtime_error( "Description of error." ); @@ -44,20 +44,19 @@ throw QString( "Description of error." ); throw "Description of error."; throw; // Whatever prints "unknown error" - } /** ***************************************************************************/ -Template::Extension::~Extension() { +ProjectNamespace::Extension::~Extension() { } /** ***************************************************************************/ -QWidget *Template::Extension::widget(QWidget *parent) { +QWidget *ProjectNamespace::Extension::widget(QWidget *parent) { if (d->widget.isNull()) { d->widget = new ConfigWidget(parent); } @@ -67,21 +66,21 @@ /** ***************************************************************************/ -void Template::Extension::setupSession() { +void ProjectNamespace::Extension::setupSession() { } /** ***************************************************************************/ -void Template::Extension::teardownSession() { +void ProjectNamespace::Extension::teardownSession() { } /** ***************************************************************************/ -void Template::Extension::handleQuery(Core::Query * query) { +void ProjectNamespace::Extension::handleQuery(Core::Query * query) { // Avoid annoying warnings Q_UNUSED(query) } diff -Nru albert-0.9.4/src/plugins/templateExtension/src/main.h albert-0.10.1/src/plugins/templateExtension/src/main.h --- albert-0.9.4/src/plugins/templateExtension/src/main.h 2017-03-01 10:22:31.000000000 +0000 +++ albert-0.10.1/src/plugins/templateExtension/src/main.h 2017-03-20 15:24:06.000000000 +0000 @@ -20,9 +20,9 @@ #include "extension.h" #include "queryhandler.h" -namespace Template { +namespace ProjectNamespace { -class TemplatePrivate; +class ProjectNamespacePrivate; class ConfigWidget; class Extension final : @@ -54,7 +54,7 @@ private: - std::unique_ptr d; + std::unique_ptr d; }; } diff -Nru albert-0.9.4/src/plugins/terminal/src/main.cpp albert-0.10.1/src/plugins/terminal/src/main.cpp --- albert-0.9.4/src/plugins/terminal/src/main.cpp 2017-03-01 10:22:31.000000000 +0000 +++ albert-0.10.1/src/plugins/terminal/src/main.cpp 2017-03-20 15:24:06.000000000 +0000 @@ -20,6 +20,8 @@ #include #include #include +#include +#include #include #include #include @@ -46,10 +48,8 @@ QPointer widget; QFileSystemWatcher watcher; std::set index; - bool dirtyFlag; QString iconPath; - - void rebuildIndex(); + bool dirtyFlag; }; @@ -67,7 +67,7 @@ connect(&d->watcher, &QFileSystemWatcher::directoryChanged, [this](){ d->dirtyFlag = true; }); - d->rebuildIndex(); + rebuildIndex(); } @@ -93,7 +93,7 @@ void Terminal::Extension::teardownSession() { if ( d->dirtyFlag ) // Build rebuild the chache - d->rebuildIndex(); + rebuildIndex(); } @@ -105,6 +105,7 @@ // Drop the query QString actualQuery = query->searchTerm().mid(1); + QString shell = QProcessEnvironment::systemEnvironment().value("SHELL"); // Extract data from input string: [0] program. The rest: args QString potentialProgram = actualQuery.section(' ', 0, 0, QString::SectionSkipEmpty); @@ -122,40 +123,34 @@ std::vector> actions; shared_ptr action = std::make_shared(); - action->setText("Execute in background"); - action->setAction([program, args](){ - QProcess::startDetached(program, args); + action->setText("Execute in the shell"); + action->setAction([shell, commandlineString](){ + QProcess::startDetached(QString("%1 -ic \"%2\"").arg(shell, commandlineString)); }); actions.push_back(std::move(action)); - QStringList cmddline = terminalCommand.split(' ', QString::SkipEmptyParts); - cmddline.append(program); - cmddline.append(args); action = std::make_shared(); - action->setText("Execute in terminal"); - action->setAction([cmddline](){ - QStringList args = cmddline; - QString program = args.takeFirst(); - QProcess::startDetached(program, args); + action->setText("Execute in the terminal"); + action->setAction([shell, commandlineString](){ + QStringList cmdLineFields = terminalCommand.split(' ', QString::SkipEmptyParts); + cmdLineFields.append(QString("%1 -ic '%2; exec %1'").arg(shell, commandlineString)); + QProcess::startDetached(cmdLineFields.takeFirst(), cmdLineFields); }); actions.push_back(std::move(action)); - cmddline = terminalCommand.split(' ', QString::SkipEmptyParts); - cmddline.append("sudo"); - cmddline.append(program); - cmddline.append(args); action = std::make_shared(); action->setText("Execute as root in terminal"); - action->setAction([cmddline](){ - QStringList args = cmddline; - QString program = args.takeFirst(); - QProcess::startDetached(program, args); + action->setAction([shell, commandlineString](){ + QStringList cmdLineFields = terminalCommand.split(' ', QString::SkipEmptyParts); + cmdLineFields.append(QString("%1 -ic 'sudo %2; exec %1'").arg(shell, commandlineString)); + QProcess::startDetached(cmdLineFields.takeFirst(), cmdLineFields); }); actions.push_back(std::move(action)); std::shared_ptr item = std::make_shared(program); item->setText(commandlineString); item->setSubtext(QString("Run '%1'").arg(commandlineString)); + item->setCompletionString(QString(">%1").arg(commandlineString)); item->setIconPath(d->iconPath); item->setActions(std::move(actions)); @@ -170,8 +165,11 @@ /** ***************************************************************************/ -void Terminal::TerminalPrivate::rebuildIndex() { - index.clear(); +void Terminal::Extension::rebuildIndex() { + + std::set index; + + // Index the executables in the path QStringList paths = QString(::getenv("PATH")).split(':', QString::SkipEmptyParts); for (const QString &path : paths) { QDirIterator dirIt(path); @@ -181,4 +179,20 @@ index.insert(file.fileName()); } } + + // If env contains the shell index the aliases + QProcess process; + process.start(QString("%1 -ic \"alias\"").arg(QProcessEnvironment::systemEnvironment().value("SHELL"))); + if ( !process.waitForFinished(100) ) + return; + QTextStream standardout(process.readAllStandardOutput()); + QRegularExpression regex("(?<=alias )\\w*"); + while (!standardout.atEnd()){ + QString line = standardout.readLine(); + QRegularExpressionMatch match = regex.match(line); + if (match.hasMatch()) + index.insert(match.captured(0)); + } + + d->index = std::move(index); } diff -Nru albert-0.9.4/src/plugins/terminal/src/main.h albert-0.10.1/src/plugins/terminal/src/main.h --- albert-0.9.4/src/plugins/terminal/src/main.h 2017-03-01 10:22:31.000000000 +0000 +++ albert-0.10.1/src/plugins/terminal/src/main.h 2017-03-20 15:24:06.000000000 +0000 @@ -50,6 +50,8 @@ private: + void rebuildIndex(); + std::unique_ptr d; }; diff -Nru albert-0.9.4/src/plugins/virtualbox/CMakeLists.txt albert-0.10.1/src/plugins/virtualbox/CMakeLists.txt --- albert-0.9.4/src/plugins/virtualbox/CMakeLists.txt 2017-03-01 10:22:31.000000000 +0000 +++ albert-0.10.1/src/plugins/virtualbox/CMakeLists.txt 2017-03-20 15:24:06.000000000 +0000 @@ -2,13 +2,11 @@ PROJECT(virtualbox) -find_package(Qt5Widgets 5.2 REQUIRED) -find_package(Qt5Xml 5.2 REQUIRED) - FILE(GLOB_RECURSE SRC src/* metadata.json) find_package(Qt5 5.2.0 REQUIRED COMPONENTS Widgets + Xml ) qt5_add_resources(QRC diff -Nru albert-0.9.4/src/plugins/virtualbox/src/main.cpp albert-0.10.1/src/plugins/virtualbox/src/main.cpp --- albert-0.9.4/src/plugins/virtualbox/src/main.cpp 2017-03-01 10:22:31.000000000 +0000 +++ albert-0.10.1/src/plugins/virtualbox/src/main.cpp 2017-03-20 15:24:06.000000000 +0000 @@ -56,13 +56,13 @@ /** ***************************************************************************/ void VirtualBox::VirtualBoxPrivate::rescanVBoxConfig(QString path) { - qDebug() << qPrintable(QString("[%1] Scanning for VMs").arg(q->Core::Extension::id)); + qDebug() << "Start indexing VirtualBox images."; QFile vboxConfigFile(path); if (!vboxConfigFile.exists()) return; if (!vboxConfigFile.open(QFile::ReadOnly)) { - qCritical("Could not open VBox config file for read operation!"); + qCritical() << "Could not open VirtualBox config file for read operation!"; return; } @@ -70,7 +70,7 @@ QString errMsg = ""; int errLine = 0, errCol = 0; if (!vboxConfig.setContent(&vboxConfigFile, &errMsg, &errLine, &errCol)) { - qWarning("Parsing of VBox config failed because %s in line %d col %d", errMsg.toStdString().c_str(), errLine, errCol); + qWarning() << qPrintable(QString("Parsing VBox config failed because %s in line %d col %d").arg(errMsg).arg(errLine, errCol)); vboxConfigFile.close(); return; } @@ -78,19 +78,19 @@ QDomElement root = vboxConfig.documentElement(); if (root.isNull()) { - qCritical("root element is null"); + qCritical() << "In VBox config file: Root element is null."; return; } QDomElement global = root.firstChildElement("Global"); if (global.isNull()) { - qCritical("global element is null"); + qCritical() << "In VBox config file: Global element is null."; return; } QDomElement machines = global.firstChildElement("MachineRegistry"); // List of MachineEntry if (machines.isNull()) { - qCritical("machine registry element is null"); + qCritical() << "In VBox config file: Machine registry element is null."; return; } @@ -111,7 +111,7 @@ found++; } - qDebug() << qPrintable(QString("[%1] Found %2 VMs").arg(q->Core::Extension::id, found)); + qDebug() << qPrintable(QString("Indexed %2 VirtualBox images.").arg(found)); } diff -Nru albert-0.9.4/src/plugins/websearch/src/main.cpp albert-0.10.1/src/plugins/websearch/src/main.cpp --- albert-0.9.4/src/plugins/websearch/src/main.cpp 2017-03-01 10:22:31.000000000 +0000 +++ albert-0.10.1/src/plugins/websearch/src/main.cpp 2017-03-20 15:24:06.000000000 +0000 @@ -48,9 +48,18 @@ struct SearchEngine { bool enabled; QString name; - QString url; QString trigger; QString iconPath; + QString url; +}; + +std::vector defaultSearchEngines = { + {true, "Google", "gg ", ":google", "https://www.google.com/search?q=%s"}, + {true, "Youtube", "yt ", ":youtube", "https://www.youtube.com/results?search_query=%s"}, + {true, "Amazon", "ama ", ":amazon", "http://www.amazon.com/s/?field-keywords=%s"}, + {true, "Ebay", "eb ", ":ebay", "http://www.ebay.com/sch/i.html?_nkw=%s"}, + {true, "GitHub", "gh ", ":github", "https://github.com/search?utf8=✓&q=%s"}, + {true, "Wolfram Alpha", "=", ":wolfram", "https://www.wolframalpha.com/input/?i=%s"} }; shared_ptr buildWebsearchItem(const SearchEngine &se, const QString &searchterm) { @@ -104,19 +113,21 @@ .filePath(QString("%1.json").arg(q->Core::Extension::id))); if (!file.open(QIODevice::ReadOnly)) { - qWarning() << QString("[%1] Could not open file: %2").arg(q->Core::Extension::id,file.fileName()).toLocal8Bit().data(); + qWarning() << qPrintable(QString("Could not open file: '%1'.").arg(file.fileName())); return false; } QJsonArray array = QJsonDocument::fromJson(file.readAll()).array(); + SearchEngine searchEngine; for ( const QJsonValue& value : array) { QJsonObject object = value.toObject(); - searchEngines.emplace_back(SearchEngine{object["enabled"].toBool(), - object["name"].toString(), - object["url"].toString(), - object["trigger"].toString(), - object["iconPath"].toString()}); + searchEngine.enabled = object["enabled"].toBool(); + searchEngine.name = object["name"].toString(); + searchEngine.trigger = object["trigger"].toString(); + searchEngine.iconPath = object["iconPath"].toString(); + searchEngine.url = object["url"].toString(); + searchEngines.push_back(searchEngine); } return true; @@ -131,7 +142,7 @@ .filePath(QString("%1.json").arg(q->Core::Extension::id))); if (!file.open(QIODevice::WriteOnly)) { - qWarning() << QString("[%1] Could not open file: %2").arg(q->Core::Extension::id,file.fileName()).toLocal8Bit().data(); + qWarning() << qPrintable(QString("Could not open file: '%1'.").arg(file.fileName())); return false; } @@ -157,15 +168,7 @@ /** ***************************************************************************/ void Websearch::WebsearchPrivate::restoreDefaults() { /* Init std searches */ - searchEngines.clear(); - - searchEngines.emplace_back(SearchEngine{true, "Google", "https://www.google.com/search?q=%s", "gg ", ":google"}); - searchEngines.emplace_back(SearchEngine{true, "Youtube", "https://www.youtube.com/results?search_query=%s", "yt ", ":youtube"}); - searchEngines.emplace_back(SearchEngine{true, "Amazon", "http://www.amazon.com/s/?field-keywords=%s", "ama ", ":amazon"}); - searchEngines.emplace_back(SearchEngine{true, "Ebay", "http://www.ebay.com/sch/i.html?_nkw=%s", "eb ", ":ebay"}); - searchEngines.emplace_back(SearchEngine{true, "GitHub", "https://github.com/search?utf8=✓&q=%s", "gh ", ":github"}); - searchEngines.emplace_back(SearchEngine{true, "Wolfram Alpha", "https://www.wolframalpha.com/input/?i=%s", "=", ":wolfram"}); - + searchEngines = defaultSearchEngines; serialize(); if (!widget.isNull()) @@ -192,24 +195,22 @@ // Deserialize binary data if (dataFile.open(QIODevice::ReadOnly| QIODevice::Text)) { - qDebug("[%s] Porting from binary file: %s", Core::Extension::id.toUtf8().constData(), dataFile.fileName().toLocal8Bit().data()); + qDebug() << "Porting websearches from old format"; QDataStream in(&dataFile); quint64 size; in >> size; SearchEngine se; - bool enabled; - QString name, trigger, url, iconPath; for (quint64 i = 0; i < size; ++i) { - in >> enabled >> url >> name >> trigger >> iconPath; - d->searchEngines.emplace_back(SearchEngine{enabled, name, url, trigger, iconPath}); + in >> se.enabled >> se.url >> se.name >> se.trigger >> se.iconPath; + d->searchEngines.push_back(se); } dataFile.close(); } else - qWarning() << "Could not open file: " << dataFile.fileName(); + qWarning() << qPrintable(QString("Could not open file '%1'").arg(dataFile.fileName())); // Whatever remove it if ( !dataFile.remove() ) - qWarning() << "Could not remove file: " << dataFile.fileName(); + qWarning() << qPrintable(QString("Could not remove file '%1'").arg(dataFile.fileName())); // Hmm what to do?