diff -Nru albert-0.10.3/data/ArcTemplate.qss albert-0.11.1/data/ArcTemplate.qss --- albert-0.10.3/data/ArcTemplate.qss 2017-04-02 16:54:56.000000000 +0000 +++ albert-0.11.1/data/ArcTemplate.qss 2017-04-16 11:17:45.000000000 +0000 @@ -51,6 +51,10 @@ /********** ListViews **********/ +QListView { + selection-color: #%foreground_color%; +} + QListView::item:selected { background: #%selection_background_color%; border: 1px solid #%selection_border_color%; diff -Nru albert-0.10.3/data/SlickTemplate.qss albert-0.11.1/data/SlickTemplate.qss --- albert-0.10.3/data/SlickTemplate.qss 2017-04-02 16:54:56.000000000 +0000 +++ albert-0.11.1/data/SlickTemplate.qss 1970-01-01 00:00:00.000000000 +0000 @@ -1,87 +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) - */ - -* { - border: none; - color : #%foreground_color%; - background-color: #%background_color%; -} - -#frame { - padding: 6px 0px; - border-radius: 8px; - background-color: #%background_color%; - min-width:640px; - max-width:640px; -} - -#inputLine { - padding: 0px 8px; - font-size: 36px; - selection-color: #%background_color%; - selection-background-color: #%foreground_color%; - background-color: transparent; -} - -#settingsButton { - 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%; -} - -QListView QScrollBar:vertical { - width: 3px; - background: transparent; -} - -QListView QScrollBar::handle:vertical { - background: #%scroll_color%; - 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.10.3/data/SlickTemplate.sh albert-0.11.1/data/SlickTemplate.sh --- albert-0.10.3/data/SlickTemplate.sh 2017-04-02 16:54:56.000000000 +0000 +++ albert-0.11.1/data/SlickTemplate.sh 1970-01-01 00:00:00.000000000 +0000 @@ -1,17 +0,0 @@ -#!/bin/bash - -TEMPLATE="SlickTemplate.qss" - -function makeStyle(){ - cat "$1" | sed \ - -e "s/%background_color%/$2/g" \ - -e "s/%foreground_color%/$3/g" \ - -e "s/%button_color%/$4/g" \ - -e "s/%scroll_color%/$5/g" \ - -e "s/%selection_background_color%/$6/g" > "${7}" -} - -#makeStyle bg fg button scroll selection output -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.10.3/data/SpotlightTemplate.qss albert-0.11.1/data/SpotlightTemplate.qss --- albert-0.10.3/data/SpotlightTemplate.qss 1970-01-01 00:00:00.000000000 +0000 +++ albert-0.11.1/data/SpotlightTemplate.qss 2017-04-16 11:17:45.000000000 +0000 @@ -0,0 +1,88 @@ +/* + * 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 : #%foreground_color%; + background-color: #%background_color%; +} + +#frame { + padding: 6px 0px; + border-radius: 8px; + background-color: #%background_color%; + min-width:640px; + max-width:640px; +} + +#inputLine { + padding: 0px 8px; + font-size: 36px; + selection-color: #%background_color%; + selection-background-color: #%foreground_color%; + background-color: transparent; +} + +#settingsButton { + 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; + selection-color: #%selection_foreground_color%; +} + +QListView::item:selected { + background: #%selection_background_color%; +} + +QListView QScrollBar:vertical { + width: 3px; + background: transparent; +} + +QListView QScrollBar::handle:vertical { + background: #%scroll_color%; + 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.10.3/data/SpotlightTemplate.sh albert-0.11.1/data/SpotlightTemplate.sh --- albert-0.10.3/data/SpotlightTemplate.sh 1970-01-01 00:00:00.000000000 +0000 +++ albert-0.11.1/data/SpotlightTemplate.sh 2017-04-16 11:17:45.000000000 +0000 @@ -0,0 +1,17 @@ +#!/bin/bash + +TEMPLATE="SpotlightTemplate.qss" + +function makeStyle(){ + cat "$1" | sed \ + -e "s/%background_color%/$2/g" \ + -e "s/%foreground_color%/$3/g" \ + -e "s/%button_color%/$4/g" \ + -e "s/%scroll_color%/$5/g" \ + -e "s/%selection_foreground_color%/$6/g"\ + -e "s/%selection_background_color%/$7/g" > "${8}" +} + +#makeStyle bg fg button scroll sel_fg sel_bg output +makeStyle "$TEMPLATE" "fcfcfc" "808080" "e0e0e0" "c0c0c0" "606060" "e0e0e0" "${1}Spotlight.qss" +makeStyle "$TEMPLATE" "030303" "808080" "202020" "404040" "a0a0a0" "202020" "${1}Spotlight Dark.qss" diff -Nru albert-0.10.3/data/StandardThemeTemplate.qss albert-0.11.1/data/StandardThemeTemplate.qss --- albert-0.10.3/data/StandardThemeTemplate.qss 2017-04-02 16:54:56.000000000 +0000 +++ albert-0.11.1/data/StandardThemeTemplate.qss 2017-04-16 11:17:45.000000000 +0000 @@ -51,8 +51,13 @@ /********** ListViews **********/ +QListView { + background: transparent; + selection-color: #%selection_foreground_color%; +} + QListView::item:selected { - background: qlineargradient(x1:0, x2:1, stop:0.0 #40%selection_background_color%, stop:0.5 #20%selection_background_color%, stop:1.0 #40%selection_background_color% ); + background: qlineargradient(x1:0, x2:1, stop:0.0 #20%selection_background_color%, stop:0.5 #10%selection_background_color%, stop:1.0 #20%selection_background_color% ); } QListView QScrollBar:vertical { diff -Nru albert-0.10.3/data/StandardThemeTemplate.sh albert-0.11.1/data/StandardThemeTemplate.sh --- albert-0.10.3/data/StandardThemeTemplate.sh 2017-04-02 16:54:56.000000000 +0000 +++ albert-0.11.1/data/StandardThemeTemplate.sh 2017-04-16 11:17:45.000000000 +0000 @@ -3,46 +3,46 @@ TEMPLATE="StandardThemeTemplate.qss" function makeStyle(){ - cat "$1" | sed \ - -e "s/%background_color%/$2/g" \ - -e "s/%foreground_color%/$3/g" \ - -e "s/%inputline_color%/$4/g" \ - -e "s/%border_color%/$5/g" \ - -e "s/%button_color%/$6/g" \ - -e "s/%scroll_color%/$7/g" \ - -e "s/%selection_background_color%/$8/g" \ - -e "s/%selection_border_color%/$9/g" > "${10}" + cat "${1}" | sed \ + -e "s/%background_color%/${2}/g" \ + -e "s/%foreground_color%/${3}/g" \ + -e "s/%inputline_color%/${4}/g" \ + -e "s/%border_color%/${5}/g" \ + -e "s/%button_color%/${6}/g" \ + -e "s/%scroll_color%/${7}/g" \ + -e "s/%selection_foreground_color%/${8}/g"\ + -e "s/%selection_background_color%/${9}/g" \ + -e "s/%selection_border_color%/${10}/g" > "${11}" } -#makeStyle bg fg input border button scrollbar sel_bg sel_border output -makeStyle "$TEMPLATE" "FFFFFF" "808080" "D0D0D0" "808080" "808080" "808080" "808080" "808080" "$1/Bright.qss" -makeStyle "$TEMPLATE" "FFFFFF" "808080" "D0D0D0" "FF8000" "FF8000" "FF8000" "FF8000" "FF8000" "$1/BrightOrange.qss" -makeStyle "$TEMPLATE" "FFFFFF" "808080" "D0D0D0" "FF0080" "FF0080" "FF0080" "FF0080" "FF0080" "$1/BrightMagenta.qss" -makeStyle "$TEMPLATE" "FFFFFF" "808080" "D0D0D0" "00FF80" "00FF80" "00FF80" "00FF80" "00FF80" "$1/BrightMint.qss" -makeStyle "$TEMPLATE" "FFFFFF" "808080" "D0D0D0" "80FF00" "80FF00" "80FF00" "80FF00" "80FF00" "$1/BrightGreen.qss" -makeStyle "$TEMPLATE" "FFFFFF" "808080" "D0D0D0" "0080FF" "0080FF" "0080FF" "0080FF" "0080FF" "$1/BrightBlue.qss" -makeStyle "$TEMPLATE" "FFFFFF" "808080" "D0D0D0" "8000FF" "8000FF" "8000FF" "8000FF" "8000FF" "$1/BrightViolet.qss" -makeStyle "$TEMPLATE" "404040" "808080" "202020" "808080" "808080" "808080" "808080" "808080" "$1/Dark.qss" -makeStyle "$TEMPLATE" "404040" "808080" "202020" "FF8000" "FF8000" "FF8000" "FF8000" "FF8000" "$1/DarkOrange.qss" -makeStyle "$TEMPLATE" "404040" "808080" "202020" "FF0080" "FF0080" "FF0080" "FF0080" "FF0080" "$1/DarkMagenta.qss" -makeStyle "$TEMPLATE" "404040" "808080" "202020" "00FF80" "00FF80" "00FF80" "00FF80" "00FF80" "$1/DarkMint.qss" -makeStyle "$TEMPLATE" "404040" "808080" "202020" "80FF00" "80FF00" "80FF00" "80FF00" "80FF00" "$1/DarkGreen.qss" -makeStyle "$TEMPLATE" "404040" "808080" "202020" "0080FF" "0080FF" "0080FF" "0080FF" "0080FF" "$1/DarkBlue.qss" -makeStyle "$TEMPLATE" "404040" "808080" "202020" "8000FF" "8000FF" "8000FF" "8000FF" "8000FF" "$1/DarkViolet.qss" -makeStyle "$TEMPLATE" "002b36" "93a1a1" "073642" "b58900" "b58900" "b58900" "b58900" "b58900" "$1/SolarizedDarkYellow.qss" -makeStyle "$TEMPLATE" "002b36" "93a1a1" "073642" "cb4b16" "cb4b16" "cb4b16" "cb4b16" "cb4b16" "$1/SolarizedDarkOrange.qss" -makeStyle "$TEMPLATE" "002b36" "93a1a1" "073642" "dc322f" "dc322f" "dc322f" "dc322f" "dc322f" "$1/SolarizedDarkRed.qss" -makeStyle "$TEMPLATE" "002b36" "93a1a1" "073642" "d33682" "d33682" "d33682" "d33682" "d33682" "$1/SolarizedDarkMagenta.qss" -makeStyle "$TEMPLATE" "002b36" "93a1a1" "073642" "6c71c4" "6c71c4" "6c71c4" "6c71c4" "6c71c4" "$1/SolarizedDarkViolet.qss" -makeStyle "$TEMPLATE" "002b36" "93a1a1" "073642" "268bd2" "268bd2" "268bd2" "268bd2" "268bd2" "$1/SolarizedDarkBlue.qss" -makeStyle "$TEMPLATE" "002b36" "93a1a1" "073642" "2aa198" "2aa198" "2aa198" "2aa198" "2aa198" "$1/SolarizedDarkCyan.qss" -makeStyle "$TEMPLATE" "002b36" "93a1a1" "073642" "859900" "859900" "859900" "859900" "859900" "$1/SolarizedDarkGreen.qss" -makeStyle "$TEMPLATE" "fdf6e3" "586e75" "eee8d5" "b58900" "b58900" "b58900" "b58900" "b58900" "$1/SolarizedBrightYellow.qss" -makeStyle "$TEMPLATE" "fdf6e3" "586e75" "eee8d5" "cb4b16" "cb4b16" "cb4b16" "cb4b16" "cb4b16" "$1/SolarizedBrightOrange.qss" -makeStyle "$TEMPLATE" "fdf6e3" "586e75" "eee8d5" "dc322f" "dc322f" "dc322f" "dc322f" "dc322f" "$1/SolarizedBrightRed.qss" -makeStyle "$TEMPLATE" "fdf6e3" "586e75" "eee8d5" "d33682" "d33682" "d33682" "d33682" "d33682" "$1/SolarizedBrightMagenta.qss" -makeStyle "$TEMPLATE" "fdf6e3" "586e75" "eee8d5" "6c71c4" "6c71c4" "6c71c4" "6c71c4" "6c71c4" "$1/SolarizedBrightViolet.qss" -makeStyle "$TEMPLATE" "fdf6e3" "586e75" "eee8d5" "268bd2" "268bd2" "268bd2" "268bd2" "268bd2" "$1/SolarizedBrightBlue.qss" -makeStyle "$TEMPLATE" "fdf6e3" "586e75" "eee8d5" "2aa198" "2aa198" "2aa198" "2aa198" "2aa198" "$1/SolarizedBrightCyan.qss" -makeStyle "$TEMPLATE" "fdf6e3" "586e75" "eee8d5" "859900" "859900" "859900" "859900" "859900" "$1/SolarizedBrightGreen.qss" - +#makeStyle bg fg input border button scroll sel_fg sel_bg sel_bor output +makeStyle "$TEMPLATE" "FFFFFF" "808080" "D0D0D0" "808080" "808080" "808080" "808080" "808080" "808080" "${1}Bright.qss" +makeStyle "$TEMPLATE" "FFFFFF" "808080" "D0D0D0" "FF8000" "FF8000" "FF8000" "808080" "FF8000" "FF8000" "${1}BrightOrange.qss" +makeStyle "$TEMPLATE" "FFFFFF" "808080" "D0D0D0" "FF0080" "FF0080" "FF0080" "808080" "FF0080" "FF0080" "${1}BrightMagenta.qss" +makeStyle "$TEMPLATE" "FFFFFF" "808080" "D0D0D0" "00FF80" "00FF80" "00FF80" "808080" "00FF80" "00FF80" "${1}BrightMint.qss" +makeStyle "$TEMPLATE" "FFFFFF" "808080" "D0D0D0" "80FF00" "80FF00" "80FF00" "808080" "80FF00" "80FF00" "${1}BrightGreen.qss" +makeStyle "$TEMPLATE" "FFFFFF" "808080" "D0D0D0" "0080FF" "0080FF" "0080FF" "808080" "0080FF" "0080FF" "${1}BrightBlue.qss" +makeStyle "$TEMPLATE" "FFFFFF" "808080" "D0D0D0" "8000FF" "8000FF" "8000FF" "808080" "8000FF" "8000FF" "${1}BrightViolet.qss" +makeStyle "$TEMPLATE" "404040" "808080" "202020" "808080" "808080" "808080" "808080" "808080" "808080" "${1}Dark.qss" +makeStyle "$TEMPLATE" "404040" "808080" "202020" "FF8000" "FF8000" "FF8000" "808080" "FF8000" "FF8000" "${1}DarkOrange.qss" +makeStyle "$TEMPLATE" "404040" "808080" "202020" "FF0080" "FF0080" "FF0080" "808080" "FF0080" "FF0080" "${1}DarkMagenta.qss" +makeStyle "$TEMPLATE" "404040" "808080" "202020" "00FF80" "00FF80" "00FF80" "808080" "00FF80" "00FF80" "${1}DarkMint.qss" +makeStyle "$TEMPLATE" "404040" "808080" "202020" "80FF00" "80FF00" "80FF00" "808080" "80FF00" "80FF00" "${1}DarkGreen.qss" +makeStyle "$TEMPLATE" "404040" "808080" "202020" "0080FF" "0080FF" "0080FF" "808080" "0080FF" "0080FF" "${1}DarkBlue.qss" +makeStyle "$TEMPLATE" "404040" "808080" "202020" "8000FF" "8000FF" "8000FF" "808080" "8000FF" "8000FF" "${1}DarkViolet.qss" +makeStyle "$TEMPLATE" "002b36" "93a1a1" "073642" "b58900" "b58900" "b58900" "93a1a1" "b58900" "b58900" "${1}SolarizedDarkYellow.qss" +makeStyle "$TEMPLATE" "002b36" "93a1a1" "073642" "cb4b16" "cb4b16" "cb4b16" "93a1a1" "cb4b16" "cb4b16" "${1}SolarizedDarkOrange.qss" +makeStyle "$TEMPLATE" "002b36" "93a1a1" "073642" "dc322f" "dc322f" "dc322f" "93a1a1" "dc322f" "dc322f" "${1}SolarizedDarkRed.qss" +makeStyle "$TEMPLATE" "002b36" "93a1a1" "073642" "d33682" "d33682" "d33682" "93a1a1" "d33682" "d33682" "${1}SolarizedDarkMagenta.qss" +makeStyle "$TEMPLATE" "002b36" "93a1a1" "073642" "6c71c4" "6c71c4" "6c71c4" "93a1a1" "6c71c4" "6c71c4" "${1}SolarizedDarkViolet.qss" +makeStyle "$TEMPLATE" "002b36" "93a1a1" "073642" "268bd2" "268bd2" "268bd2" "93a1a1" "268bd2" "268bd2" "${1}SolarizedDarkBlue.qss" +makeStyle "$TEMPLATE" "002b36" "93a1a1" "073642" "2aa198" "2aa198" "2aa198" "93a1a1" "2aa198" "2aa198" "${1}SolarizedDarkCyan.qss" +makeStyle "$TEMPLATE" "002b36" "93a1a1" "073642" "859900" "859900" "859900" "93a1a1" "859900" "859900" "${1}SolarizedDarkGreen.qss" +makeStyle "$TEMPLATE" "fdf6e3" "586e75" "eee8d5" "b58900" "b58900" "b58900" "586e75" "b58900" "b58900" "${1}SolarizedBrightYellow.qss" +makeStyle "$TEMPLATE" "fdf6e3" "586e75" "eee8d5" "cb4b16" "cb4b16" "cb4b16" "586e75" "cb4b16" "cb4b16" "${1}SolarizedBrightOrange.qss" +makeStyle "$TEMPLATE" "fdf6e3" "586e75" "eee8d5" "dc322f" "dc322f" "dc322f" "586e75" "dc322f" "dc322f" "${1}SolarizedBrightRed.qss" +makeStyle "$TEMPLATE" "fdf6e3" "586e75" "eee8d5" "d33682" "d33682" "d33682" "586e75" "d33682" "d33682" "${1}SolarizedBrightMagenta.qss" +makeStyle "$TEMPLATE" "fdf6e3" "586e75" "eee8d5" "6c71c4" "6c71c4" "6c71c4" "586e75" "6c71c4" "6c71c4" "${1}SolarizedBrightViolet.qss" +makeStyle "$TEMPLATE" "fdf6e3" "586e75" "eee8d5" "268bd2" "268bd2" "268bd2" "586e75" "268bd2" "268bd2" "${1}SolarizedBrightBlue.qss" +makeStyle "$TEMPLATE" "fdf6e3" "586e75" "eee8d5" "2aa198" "2aa198" "2aa198" "586e75" "2aa198" "2aa198" "${1}SolarizedBrightCyan.qss" +makeStyle "$TEMPLATE" "fdf6e3" "586e75" "eee8d5" "859900" "859900" "859900" "586e75" "859900" "859900" "${1}SolarizedBrightGreen.qss" diff -Nru albert-0.10.3/data/themes/Arc Blue.qss albert-0.11.1/data/themes/Arc Blue.qss --- albert-0.10.3/data/themes/Arc Blue.qss 2017-04-02 16:54:56.000000000 +0000 +++ albert-0.11.1/data/themes/Arc Blue.qss 2017-04-16 11:17:45.000000000 +0000 @@ -51,6 +51,10 @@ /********** ListViews **********/ +QListView { + selection-color: #727A8F; +} + QListView::item:selected { background: #95c4fb; border: 1px solid #cfd6e6; diff -Nru albert-0.10.3/data/themes/Arc Dark Blue.qss albert-0.11.1/data/themes/Arc Dark Blue.qss --- albert-0.10.3/data/themes/Arc Dark Blue.qss 2017-04-02 16:54:56.000000000 +0000 +++ albert-0.11.1/data/themes/Arc Dark Blue.qss 2017-04-16 11:17:45.000000000 +0000 @@ -51,6 +51,10 @@ /********** ListViews **********/ +QListView { + selection-color: #AFB8C5; +} + QListView::item:selected { background: #4084D6; border: 1px solid #4084D6; diff -Nru albert-0.10.3/data/themes/Arc Dark Grey.qss albert-0.11.1/data/themes/Arc Dark Grey.qss --- albert-0.10.3/data/themes/Arc Dark Grey.qss 2017-04-02 16:54:56.000000000 +0000 +++ albert-0.11.1/data/themes/Arc Dark Grey.qss 2017-04-16 11:17:45.000000000 +0000 @@ -51,6 +51,10 @@ /********** ListViews **********/ +QListView { + selection-color: #AFB8C5; +} + QListView::item:selected { background: #404552; border: 1px solid #2B2E39; diff -Nru albert-0.10.3/data/themes/Arc Grey.qss albert-0.11.1/data/themes/Arc Grey.qss --- albert-0.10.3/data/themes/Arc Grey.qss 2017-04-02 16:54:56.000000000 +0000 +++ albert-0.11.1/data/themes/Arc Grey.qss 2017-04-16 11:17:45.000000000 +0000 @@ -51,6 +51,10 @@ /********** ListViews **********/ +QListView { + selection-color: #727A8F; +} + QListView::item:selected { background: #F5F6F7; border: 1px solid #4084D6; diff -Nru albert-0.10.3/data/themes/BrightBlue.qss albert-0.11.1/data/themes/BrightBlue.qss --- albert-0.10.3/data/themes/BrightBlue.qss 2017-04-02 16:54:56.000000000 +0000 +++ albert-0.11.1/data/themes/BrightBlue.qss 2017-04-16 11:17:45.000000000 +0000 @@ -51,8 +51,13 @@ /********** ListViews **********/ +QListView { + background: transparent; + selection-color: #808080; +} + QListView::item:selected { - background: qlineargradient(x1:0, x2:1, stop:0.0 #400080FF, stop:0.5 #200080FF, stop:1.0 #400080FF ); + background: qlineargradient(x1:0, x2:1, stop:0.0 #200080FF, stop:0.5 #100080FF, stop:1.0 #200080FF ); } QListView QScrollBar:vertical { diff -Nru albert-0.10.3/data/themes/BrightGreen.qss albert-0.11.1/data/themes/BrightGreen.qss --- albert-0.10.3/data/themes/BrightGreen.qss 2017-04-02 16:54:56.000000000 +0000 +++ albert-0.11.1/data/themes/BrightGreen.qss 2017-04-16 11:17:45.000000000 +0000 @@ -51,8 +51,13 @@ /********** ListViews **********/ +QListView { + background: transparent; + selection-color: #808080; +} + QListView::item:selected { - background: qlineargradient(x1:0, x2:1, stop:0.0 #4080FF00, stop:0.5 #2080FF00, stop:1.0 #4080FF00 ); + background: qlineargradient(x1:0, x2:1, stop:0.0 #2080FF00, stop:0.5 #1080FF00, stop:1.0 #2080FF00 ); } QListView QScrollBar:vertical { diff -Nru albert-0.10.3/data/themes/BrightMagenta.qss albert-0.11.1/data/themes/BrightMagenta.qss --- albert-0.10.3/data/themes/BrightMagenta.qss 2017-04-02 16:54:56.000000000 +0000 +++ albert-0.11.1/data/themes/BrightMagenta.qss 2017-04-16 11:17:45.000000000 +0000 @@ -51,8 +51,13 @@ /********** ListViews **********/ +QListView { + background: transparent; + selection-color: #808080; +} + QListView::item:selected { - background: qlineargradient(x1:0, x2:1, stop:0.0 #40FF0080, stop:0.5 #20FF0080, stop:1.0 #40FF0080 ); + background: qlineargradient(x1:0, x2:1, stop:0.0 #20FF0080, stop:0.5 #10FF0080, stop:1.0 #20FF0080 ); } QListView QScrollBar:vertical { diff -Nru albert-0.10.3/data/themes/BrightMint.qss albert-0.11.1/data/themes/BrightMint.qss --- albert-0.10.3/data/themes/BrightMint.qss 2017-04-02 16:54:56.000000000 +0000 +++ albert-0.11.1/data/themes/BrightMint.qss 2017-04-16 11:17:45.000000000 +0000 @@ -51,8 +51,13 @@ /********** ListViews **********/ +QListView { + background: transparent; + selection-color: #808080; +} + QListView::item:selected { - background: qlineargradient(x1:0, x2:1, stop:0.0 #4000FF80, stop:0.5 #2000FF80, stop:1.0 #4000FF80 ); + background: qlineargradient(x1:0, x2:1, stop:0.0 #2000FF80, stop:0.5 #1000FF80, stop:1.0 #2000FF80 ); } QListView QScrollBar:vertical { diff -Nru albert-0.10.3/data/themes/BrightOrange.qss albert-0.11.1/data/themes/BrightOrange.qss --- albert-0.10.3/data/themes/BrightOrange.qss 2017-04-02 16:54:56.000000000 +0000 +++ albert-0.11.1/data/themes/BrightOrange.qss 2017-04-16 11:17:45.000000000 +0000 @@ -51,8 +51,13 @@ /********** ListViews **********/ +QListView { + background: transparent; + selection-color: #808080; +} + QListView::item:selected { - background: qlineargradient(x1:0, x2:1, stop:0.0 #40FF8000, stop:0.5 #20FF8000, stop:1.0 #40FF8000 ); + background: qlineargradient(x1:0, x2:1, stop:0.0 #20FF8000, stop:0.5 #10FF8000, stop:1.0 #20FF8000 ); } QListView QScrollBar:vertical { diff -Nru albert-0.10.3/data/themes/Bright.qss albert-0.11.1/data/themes/Bright.qss --- albert-0.10.3/data/themes/Bright.qss 2017-04-02 16:54:56.000000000 +0000 +++ albert-0.11.1/data/themes/Bright.qss 2017-04-16 11:17:45.000000000 +0000 @@ -51,8 +51,13 @@ /********** ListViews **********/ +QListView { + background: transparent; + selection-color: #808080; +} + QListView::item:selected { - background: qlineargradient(x1:0, x2:1, stop:0.0 #40808080, stop:0.5 #20808080, stop:1.0 #40808080 ); + background: qlineargradient(x1:0, x2:1, stop:0.0 #20808080, stop:0.5 #10808080, stop:1.0 #20808080 ); } QListView QScrollBar:vertical { diff -Nru albert-0.10.3/data/themes/BrightViolet.qss albert-0.11.1/data/themes/BrightViolet.qss --- albert-0.10.3/data/themes/BrightViolet.qss 2017-04-02 16:54:56.000000000 +0000 +++ albert-0.11.1/data/themes/BrightViolet.qss 2017-04-16 11:17:45.000000000 +0000 @@ -51,8 +51,13 @@ /********** ListViews **********/ +QListView { + background: transparent; + selection-color: #808080; +} + QListView::item:selected { - background: qlineargradient(x1:0, x2:1, stop:0.0 #408000FF, stop:0.5 #208000FF, stop:1.0 #408000FF ); + background: qlineargradient(x1:0, x2:1, stop:0.0 #208000FF, stop:0.5 #108000FF, stop:1.0 #208000FF ); } QListView QScrollBar:vertical { diff -Nru albert-0.10.3/data/themes/DarkBlue.qss albert-0.11.1/data/themes/DarkBlue.qss --- albert-0.10.3/data/themes/DarkBlue.qss 2017-04-02 16:54:56.000000000 +0000 +++ albert-0.11.1/data/themes/DarkBlue.qss 2017-04-16 11:17:45.000000000 +0000 @@ -51,8 +51,13 @@ /********** ListViews **********/ +QListView { + background: transparent; + selection-color: #808080; +} + QListView::item:selected { - background: qlineargradient(x1:0, x2:1, stop:0.0 #400080FF, stop:0.5 #200080FF, stop:1.0 #400080FF ); + background: qlineargradient(x1:0, x2:1, stop:0.0 #200080FF, stop:0.5 #100080FF, stop:1.0 #200080FF ); } QListView QScrollBar:vertical { diff -Nru albert-0.10.3/data/themes/DarkGreen.qss albert-0.11.1/data/themes/DarkGreen.qss --- albert-0.10.3/data/themes/DarkGreen.qss 2017-04-02 16:54:56.000000000 +0000 +++ albert-0.11.1/data/themes/DarkGreen.qss 2017-04-16 11:17:45.000000000 +0000 @@ -51,8 +51,13 @@ /********** ListViews **********/ +QListView { + background: transparent; + selection-color: #808080; +} + QListView::item:selected { - background: qlineargradient(x1:0, x2:1, stop:0.0 #4080FF00, stop:0.5 #2080FF00, stop:1.0 #4080FF00 ); + background: qlineargradient(x1:0, x2:1, stop:0.0 #2080FF00, stop:0.5 #1080FF00, stop:1.0 #2080FF00 ); } QListView QScrollBar:vertical { diff -Nru albert-0.10.3/data/themes/DarkMagenta.qss albert-0.11.1/data/themes/DarkMagenta.qss --- albert-0.10.3/data/themes/DarkMagenta.qss 2017-04-02 16:54:56.000000000 +0000 +++ albert-0.11.1/data/themes/DarkMagenta.qss 2017-04-16 11:17:45.000000000 +0000 @@ -51,8 +51,13 @@ /********** ListViews **********/ +QListView { + background: transparent; + selection-color: #808080; +} + QListView::item:selected { - background: qlineargradient(x1:0, x2:1, stop:0.0 #40FF0080, stop:0.5 #20FF0080, stop:1.0 #40FF0080 ); + background: qlineargradient(x1:0, x2:1, stop:0.0 #20FF0080, stop:0.5 #10FF0080, stop:1.0 #20FF0080 ); } QListView QScrollBar:vertical { diff -Nru albert-0.10.3/data/themes/DarkMint.qss albert-0.11.1/data/themes/DarkMint.qss --- albert-0.10.3/data/themes/DarkMint.qss 2017-04-02 16:54:56.000000000 +0000 +++ albert-0.11.1/data/themes/DarkMint.qss 2017-04-16 11:17:45.000000000 +0000 @@ -51,8 +51,13 @@ /********** ListViews **********/ +QListView { + background: transparent; + selection-color: #808080; +} + QListView::item:selected { - background: qlineargradient(x1:0, x2:1, stop:0.0 #4000FF80, stop:0.5 #2000FF80, stop:1.0 #4000FF80 ); + background: qlineargradient(x1:0, x2:1, stop:0.0 #2000FF80, stop:0.5 #1000FF80, stop:1.0 #2000FF80 ); } QListView QScrollBar:vertical { diff -Nru albert-0.10.3/data/themes/DarkOrange.qss albert-0.11.1/data/themes/DarkOrange.qss --- albert-0.10.3/data/themes/DarkOrange.qss 2017-04-02 16:54:56.000000000 +0000 +++ albert-0.11.1/data/themes/DarkOrange.qss 2017-04-16 11:17:45.000000000 +0000 @@ -51,8 +51,13 @@ /********** ListViews **********/ +QListView { + background: transparent; + selection-color: #808080; +} + QListView::item:selected { - background: qlineargradient(x1:0, x2:1, stop:0.0 #40FF8000, stop:0.5 #20FF8000, stop:1.0 #40FF8000 ); + background: qlineargradient(x1:0, x2:1, stop:0.0 #20FF8000, stop:0.5 #10FF8000, stop:1.0 #20FF8000 ); } QListView QScrollBar:vertical { diff -Nru albert-0.10.3/data/themes/Dark.qss albert-0.11.1/data/themes/Dark.qss --- albert-0.10.3/data/themes/Dark.qss 2017-04-02 16:54:56.000000000 +0000 +++ albert-0.11.1/data/themes/Dark.qss 2017-04-16 11:17:45.000000000 +0000 @@ -51,8 +51,13 @@ /********** ListViews **********/ +QListView { + background: transparent; + selection-color: #808080; +} + QListView::item:selected { - background: qlineargradient(x1:0, x2:1, stop:0.0 #40808080, stop:0.5 #20808080, stop:1.0 #40808080 ); + background: qlineargradient(x1:0, x2:1, stop:0.0 #20808080, stop:0.5 #10808080, stop:1.0 #20808080 ); } QListView QScrollBar:vertical { diff -Nru albert-0.10.3/data/themes/DarkViolet.qss albert-0.11.1/data/themes/DarkViolet.qss --- albert-0.10.3/data/themes/DarkViolet.qss 2017-04-02 16:54:56.000000000 +0000 +++ albert-0.11.1/data/themes/DarkViolet.qss 2017-04-16 11:17:45.000000000 +0000 @@ -51,8 +51,13 @@ /********** ListViews **********/ +QListView { + background: transparent; + selection-color: #808080; +} + QListView::item:selected { - background: qlineargradient(x1:0, x2:1, stop:0.0 #408000FF, stop:0.5 #208000FF, stop:1.0 #408000FF ); + background: qlineargradient(x1:0, x2:1, stop:0.0 #208000FF, stop:0.5 #108000FF, stop:1.0 #208000FF ); } QListView QScrollBar:vertical { diff -Nru albert-0.10.3/data/themes/Elementary.qss albert-0.11.1/data/themes/Elementary.qss --- albert-0.10.3/data/themes/Elementary.qss 2017-04-02 16:54:56.000000000 +0000 +++ albert-0.11.1/data/themes/Elementary.qss 2017-04-16 11:17:45.000000000 +0000 @@ -9,7 +9,7 @@ * { border: none; color : #808080; - background-color: #404040; + background-color: #404040; } @@ -54,7 +54,9 @@ } /********** ListViews **********/ + QListView { + selection-color: #ccc; background-color: #F5F5F5; } @@ -75,7 +77,7 @@ QListView QScrollBar::handle:vertical { background: #808080; - min-height: 24px; + min-height: 24px; } QListView QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical, diff -Nru albert-0.10.3/data/themes/Numix.qss albert-0.11.1/data/themes/Numix.qss --- albert-0.10.3/data/themes/Numix.qss 2017-04-02 16:54:56.000000000 +0000 +++ albert-0.11.1/data/themes/Numix.qss 2017-04-16 11:17:45.000000000 +0000 @@ -56,6 +56,11 @@ /********** ListViews **********/ + +QListView { + selection-color: #ccc; +} + QListView::item:selected { border: none; background: qlineargradient(x1:0, x2:1, stop:0.0 #3a3a3a, stop:0.5 #3a3a3a, stop:1.0 #3a3a3a ); diff -Nru albert-0.10.3/data/themes/Numix Rounded.qss albert-0.11.1/data/themes/Numix Rounded.qss --- albert-0.10.3/data/themes/Numix Rounded.qss 2017-04-02 16:54:56.000000000 +0000 +++ albert-0.11.1/data/themes/Numix Rounded.qss 2017-04-16 11:17:45.000000000 +0000 @@ -58,6 +58,10 @@ /********** ListViews ************/ +QListView { + selection-color: #ccc; +} + QListView::item:selected { border: none; background: qlineargradient(x1:0, x2:1, stop:0.0 #3a3a3a, stop:0.5 #3a3a3a, stop:1.0 #3a3a3a ); diff -Nru albert-0.10.3/data/themes/SolarizedBrightBlue.qss albert-0.11.1/data/themes/SolarizedBrightBlue.qss --- albert-0.10.3/data/themes/SolarizedBrightBlue.qss 2017-04-02 16:54:56.000000000 +0000 +++ albert-0.11.1/data/themes/SolarizedBrightBlue.qss 2017-04-16 11:17:45.000000000 +0000 @@ -51,8 +51,13 @@ /********** ListViews **********/ +QListView { + background: transparent; + selection-color: #586e75; +} + QListView::item:selected { - background: qlineargradient(x1:0, x2:1, stop:0.0 #40268bd2, stop:0.5 #20268bd2, stop:1.0 #40268bd2 ); + background: qlineargradient(x1:0, x2:1, stop:0.0 #20268bd2, stop:0.5 #10268bd2, stop:1.0 #20268bd2 ); } QListView QScrollBar:vertical { diff -Nru albert-0.10.3/data/themes/SolarizedBrightCyan.qss albert-0.11.1/data/themes/SolarizedBrightCyan.qss --- albert-0.10.3/data/themes/SolarizedBrightCyan.qss 2017-04-02 16:54:56.000000000 +0000 +++ albert-0.11.1/data/themes/SolarizedBrightCyan.qss 2017-04-16 11:17:45.000000000 +0000 @@ -51,8 +51,13 @@ /********** ListViews **********/ +QListView { + background: transparent; + selection-color: #586e75; +} + QListView::item:selected { - background: qlineargradient(x1:0, x2:1, stop:0.0 #402aa198, stop:0.5 #202aa198, stop:1.0 #402aa198 ); + background: qlineargradient(x1:0, x2:1, stop:0.0 #202aa198, stop:0.5 #102aa198, stop:1.0 #202aa198 ); } QListView QScrollBar:vertical { diff -Nru albert-0.10.3/data/themes/SolarizedBrightGreen.qss albert-0.11.1/data/themes/SolarizedBrightGreen.qss --- albert-0.10.3/data/themes/SolarizedBrightGreen.qss 2017-04-02 16:54:56.000000000 +0000 +++ albert-0.11.1/data/themes/SolarizedBrightGreen.qss 2017-04-16 11:17:45.000000000 +0000 @@ -51,8 +51,13 @@ /********** ListViews **********/ +QListView { + background: transparent; + selection-color: #586e75; +} + QListView::item:selected { - background: qlineargradient(x1:0, x2:1, stop:0.0 #40859900, stop:0.5 #20859900, stop:1.0 #40859900 ); + background: qlineargradient(x1:0, x2:1, stop:0.0 #20859900, stop:0.5 #10859900, stop:1.0 #20859900 ); } QListView QScrollBar:vertical { diff -Nru albert-0.10.3/data/themes/SolarizedBrightMagenta.qss albert-0.11.1/data/themes/SolarizedBrightMagenta.qss --- albert-0.10.3/data/themes/SolarizedBrightMagenta.qss 2017-04-02 16:54:56.000000000 +0000 +++ albert-0.11.1/data/themes/SolarizedBrightMagenta.qss 2017-04-16 11:17:45.000000000 +0000 @@ -51,8 +51,13 @@ /********** ListViews **********/ +QListView { + background: transparent; + selection-color: #586e75; +} + QListView::item:selected { - background: qlineargradient(x1:0, x2:1, stop:0.0 #40d33682, stop:0.5 #20d33682, stop:1.0 #40d33682 ); + background: qlineargradient(x1:0, x2:1, stop:0.0 #20d33682, stop:0.5 #10d33682, stop:1.0 #20d33682 ); } QListView QScrollBar:vertical { diff -Nru albert-0.10.3/data/themes/SolarizedBrightOrange.qss albert-0.11.1/data/themes/SolarizedBrightOrange.qss --- albert-0.10.3/data/themes/SolarizedBrightOrange.qss 2017-04-02 16:54:56.000000000 +0000 +++ albert-0.11.1/data/themes/SolarizedBrightOrange.qss 2017-04-16 11:17:45.000000000 +0000 @@ -51,8 +51,13 @@ /********** ListViews **********/ +QListView { + background: transparent; + selection-color: #586e75; +} + QListView::item:selected { - background: qlineargradient(x1:0, x2:1, stop:0.0 #40cb4b16, stop:0.5 #20cb4b16, stop:1.0 #40cb4b16 ); + background: qlineargradient(x1:0, x2:1, stop:0.0 #20cb4b16, stop:0.5 #10cb4b16, stop:1.0 #20cb4b16 ); } QListView QScrollBar:vertical { diff -Nru albert-0.10.3/data/themes/SolarizedBrightRed.qss albert-0.11.1/data/themes/SolarizedBrightRed.qss --- albert-0.10.3/data/themes/SolarizedBrightRed.qss 2017-04-02 16:54:56.000000000 +0000 +++ albert-0.11.1/data/themes/SolarizedBrightRed.qss 2017-04-16 11:17:45.000000000 +0000 @@ -51,8 +51,13 @@ /********** ListViews **********/ +QListView { + background: transparent; + selection-color: #586e75; +} + QListView::item:selected { - background: qlineargradient(x1:0, x2:1, stop:0.0 #40dc322f, stop:0.5 #20dc322f, stop:1.0 #40dc322f ); + background: qlineargradient(x1:0, x2:1, stop:0.0 #20dc322f, stop:0.5 #10dc322f, stop:1.0 #20dc322f ); } QListView QScrollBar:vertical { diff -Nru albert-0.10.3/data/themes/SolarizedBrightViolet.qss albert-0.11.1/data/themes/SolarizedBrightViolet.qss --- albert-0.10.3/data/themes/SolarizedBrightViolet.qss 2017-04-02 16:54:56.000000000 +0000 +++ albert-0.11.1/data/themes/SolarizedBrightViolet.qss 2017-04-16 11:17:45.000000000 +0000 @@ -51,8 +51,13 @@ /********** ListViews **********/ +QListView { + background: transparent; + selection-color: #586e75; +} + QListView::item:selected { - background: qlineargradient(x1:0, x2:1, stop:0.0 #406c71c4, stop:0.5 #206c71c4, stop:1.0 #406c71c4 ); + background: qlineargradient(x1:0, x2:1, stop:0.0 #206c71c4, stop:0.5 #106c71c4, stop:1.0 #206c71c4 ); } QListView QScrollBar:vertical { diff -Nru albert-0.10.3/data/themes/SolarizedBrightYellow.qss albert-0.11.1/data/themes/SolarizedBrightYellow.qss --- albert-0.10.3/data/themes/SolarizedBrightYellow.qss 2017-04-02 16:54:56.000000000 +0000 +++ albert-0.11.1/data/themes/SolarizedBrightYellow.qss 2017-04-16 11:17:45.000000000 +0000 @@ -51,8 +51,13 @@ /********** ListViews **********/ +QListView { + background: transparent; + selection-color: #586e75; +} + QListView::item:selected { - background: qlineargradient(x1:0, x2:1, stop:0.0 #40b58900, stop:0.5 #20b58900, stop:1.0 #40b58900 ); + background: qlineargradient(x1:0, x2:1, stop:0.0 #20b58900, stop:0.5 #10b58900, stop:1.0 #20b58900 ); } QListView QScrollBar:vertical { diff -Nru albert-0.10.3/data/themes/SolarizedDarkBlue.qss albert-0.11.1/data/themes/SolarizedDarkBlue.qss --- albert-0.10.3/data/themes/SolarizedDarkBlue.qss 2017-04-02 16:54:56.000000000 +0000 +++ albert-0.11.1/data/themes/SolarizedDarkBlue.qss 2017-04-16 11:17:45.000000000 +0000 @@ -51,8 +51,13 @@ /********** ListViews **********/ +QListView { + background: transparent; + selection-color: #93a1a1; +} + QListView::item:selected { - background: qlineargradient(x1:0, x2:1, stop:0.0 #40268bd2, stop:0.5 #20268bd2, stop:1.0 #40268bd2 ); + background: qlineargradient(x1:0, x2:1, stop:0.0 #20268bd2, stop:0.5 #10268bd2, stop:1.0 #20268bd2 ); } QListView QScrollBar:vertical { diff -Nru albert-0.10.3/data/themes/SolarizedDarkCyan.qss albert-0.11.1/data/themes/SolarizedDarkCyan.qss --- albert-0.10.3/data/themes/SolarizedDarkCyan.qss 2017-04-02 16:54:56.000000000 +0000 +++ albert-0.11.1/data/themes/SolarizedDarkCyan.qss 2017-04-16 11:17:45.000000000 +0000 @@ -51,8 +51,13 @@ /********** ListViews **********/ +QListView { + background: transparent; + selection-color: #93a1a1; +} + QListView::item:selected { - background: qlineargradient(x1:0, x2:1, stop:0.0 #402aa198, stop:0.5 #202aa198, stop:1.0 #402aa198 ); + background: qlineargradient(x1:0, x2:1, stop:0.0 #202aa198, stop:0.5 #102aa198, stop:1.0 #202aa198 ); } QListView QScrollBar:vertical { diff -Nru albert-0.10.3/data/themes/SolarizedDarkGreen.qss albert-0.11.1/data/themes/SolarizedDarkGreen.qss --- albert-0.10.3/data/themes/SolarizedDarkGreen.qss 2017-04-02 16:54:56.000000000 +0000 +++ albert-0.11.1/data/themes/SolarizedDarkGreen.qss 2017-04-16 11:17:45.000000000 +0000 @@ -51,8 +51,13 @@ /********** ListViews **********/ +QListView { + background: transparent; + selection-color: #93a1a1; +} + QListView::item:selected { - background: qlineargradient(x1:0, x2:1, stop:0.0 #40859900, stop:0.5 #20859900, stop:1.0 #40859900 ); + background: qlineargradient(x1:0, x2:1, stop:0.0 #20859900, stop:0.5 #10859900, stop:1.0 #20859900 ); } QListView QScrollBar:vertical { diff -Nru albert-0.10.3/data/themes/SolarizedDarkMagenta.qss albert-0.11.1/data/themes/SolarizedDarkMagenta.qss --- albert-0.10.3/data/themes/SolarizedDarkMagenta.qss 2017-04-02 16:54:56.000000000 +0000 +++ albert-0.11.1/data/themes/SolarizedDarkMagenta.qss 2017-04-16 11:17:45.000000000 +0000 @@ -51,8 +51,13 @@ /********** ListViews **********/ +QListView { + background: transparent; + selection-color: #93a1a1; +} + QListView::item:selected { - background: qlineargradient(x1:0, x2:1, stop:0.0 #40d33682, stop:0.5 #20d33682, stop:1.0 #40d33682 ); + background: qlineargradient(x1:0, x2:1, stop:0.0 #20d33682, stop:0.5 #10d33682, stop:1.0 #20d33682 ); } QListView QScrollBar:vertical { diff -Nru albert-0.10.3/data/themes/SolarizedDarkOrange.qss albert-0.11.1/data/themes/SolarizedDarkOrange.qss --- albert-0.10.3/data/themes/SolarizedDarkOrange.qss 2017-04-02 16:54:56.000000000 +0000 +++ albert-0.11.1/data/themes/SolarizedDarkOrange.qss 2017-04-16 11:17:45.000000000 +0000 @@ -51,8 +51,13 @@ /********** ListViews **********/ +QListView { + background: transparent; + selection-color: #93a1a1; +} + QListView::item:selected { - background: qlineargradient(x1:0, x2:1, stop:0.0 #40cb4b16, stop:0.5 #20cb4b16, stop:1.0 #40cb4b16 ); + background: qlineargradient(x1:0, x2:1, stop:0.0 #20cb4b16, stop:0.5 #10cb4b16, stop:1.0 #20cb4b16 ); } QListView QScrollBar:vertical { diff -Nru albert-0.10.3/data/themes/SolarizedDarkRed.qss albert-0.11.1/data/themes/SolarizedDarkRed.qss --- albert-0.10.3/data/themes/SolarizedDarkRed.qss 2017-04-02 16:54:56.000000000 +0000 +++ albert-0.11.1/data/themes/SolarizedDarkRed.qss 2017-04-16 11:17:45.000000000 +0000 @@ -51,8 +51,13 @@ /********** ListViews **********/ +QListView { + background: transparent; + selection-color: #93a1a1; +} + QListView::item:selected { - background: qlineargradient(x1:0, x2:1, stop:0.0 #40dc322f, stop:0.5 #20dc322f, stop:1.0 #40dc322f ); + background: qlineargradient(x1:0, x2:1, stop:0.0 #20dc322f, stop:0.5 #10dc322f, stop:1.0 #20dc322f ); } QListView QScrollBar:vertical { diff -Nru albert-0.10.3/data/themes/SolarizedDarkViolet.qss albert-0.11.1/data/themes/SolarizedDarkViolet.qss --- albert-0.10.3/data/themes/SolarizedDarkViolet.qss 2017-04-02 16:54:56.000000000 +0000 +++ albert-0.11.1/data/themes/SolarizedDarkViolet.qss 2017-04-16 11:17:45.000000000 +0000 @@ -51,8 +51,13 @@ /********** ListViews **********/ +QListView { + background: transparent; + selection-color: #93a1a1; +} + QListView::item:selected { - background: qlineargradient(x1:0, x2:1, stop:0.0 #406c71c4, stop:0.5 #206c71c4, stop:1.0 #406c71c4 ); + background: qlineargradient(x1:0, x2:1, stop:0.0 #206c71c4, stop:0.5 #106c71c4, stop:1.0 #206c71c4 ); } QListView QScrollBar:vertical { diff -Nru albert-0.10.3/data/themes/SolarizedDarkYellow.qss albert-0.11.1/data/themes/SolarizedDarkYellow.qss --- albert-0.10.3/data/themes/SolarizedDarkYellow.qss 2017-04-02 16:54:56.000000000 +0000 +++ albert-0.11.1/data/themes/SolarizedDarkYellow.qss 2017-04-16 11:17:45.000000000 +0000 @@ -51,8 +51,13 @@ /********** ListViews **********/ +QListView { + background: transparent; + selection-color: #93a1a1; +} + QListView::item:selected { - background: qlineargradient(x1:0, x2:1, stop:0.0 #40b58900, stop:0.5 #20b58900, stop:1.0 #40b58900 ); + background: qlineargradient(x1:0, x2:1, stop:0.0 #20b58900, stop:0.5 #10b58900, stop:1.0 #20b58900 ); } QListView QScrollBar:vertical { diff -Nru albert-0.10.3/data/themes/Spotlight Dark.qss albert-0.11.1/data/themes/Spotlight Dark.qss --- albert-0.10.3/data/themes/Spotlight Dark.qss 2017-04-02 16:54:56.000000000 +0000 +++ albert-0.11.1/data/themes/Spotlight Dark.qss 2017-04-16 11:17:45.000000000 +0000 @@ -43,6 +43,7 @@ QListView { background: transparent; + selection-color: #a0a0a0; } QListView::item:selected { diff -Nru albert-0.10.3/data/themes/Spotlight.qss albert-0.11.1/data/themes/Spotlight.qss --- albert-0.10.3/data/themes/Spotlight.qss 2017-04-02 16:54:56.000000000 +0000 +++ albert-0.11.1/data/themes/Spotlight.qss 2017-04-16 11:17:45.000000000 +0000 @@ -43,6 +43,7 @@ QListView { background: transparent; + selection-color: #606060; } QListView::item:selected { diff -Nru albert-0.10.3/data/themes/Spotlight Space.qss albert-0.11.1/data/themes/Spotlight Space.qss --- albert-0.10.3/data/themes/Spotlight Space.qss 2017-04-02 16:54:56.000000000 +0000 +++ albert-0.11.1/data/themes/Spotlight Space.qss 1970-01-01 00:00:00.000000000 +0000 @@ -1,93 +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) - */ - -* { - 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.10.3/data/themes/Yosemite Dark.qss albert-0.11.1/data/themes/Yosemite Dark.qss --- albert-0.10.3/data/themes/Yosemite Dark.qss 2017-04-02 16:54:56.000000000 +0000 +++ albert-0.11.1/data/themes/Yosemite Dark.qss 2017-04-16 11:17:45.000000000 +0000 @@ -46,6 +46,10 @@ /********** ListViews ************/ +QListView { + selection-color: #ffffff; +} + QListView::item:selected { background: #262626; } diff -Nru albert-0.10.3/data/themes/Yosemite.qss albert-0.11.1/data/themes/Yosemite.qss --- albert-0.10.3/data/themes/Yosemite.qss 2017-04-02 16:54:56.000000000 +0000 +++ albert-0.11.1/data/themes/Yosemite.qss 2017-04-16 11:17:45.000000000 +0000 @@ -46,6 +46,10 @@ /********** ListViews ************/ +QListView { + selection-color: #000000; +} + QListView::item:selected { background: #eeeeee; } diff -Nru albert-0.10.3/debian/changelog albert-0.11.1/debian/changelog --- albert-0.10.3/debian/changelog 2017-04-03 09:35:14.000000000 +0000 +++ albert-0.11.1/debian/changelog 2017-04-18 09:35:15.000000000 +0000 @@ -1,4 +1,10 @@ -albert (0.10.3-1~webupd8~vivid0) vivid; urgency=medium +albert (0.11.1-1~webupd8~vivid0) vivid; urgency=medium + + * New upstream release + + -- Alin Andrei Tue, 18 Apr 2017 12:33:21 +0200 + +albert (0.10.3-1~webupd8~zesty1) zesty; urgency=medium * New upstream release diff -Nru albert-0.10.3/README.md albert-0.11.1/README.md --- albert-0.10.3/README.md 2017-04-02 16:54:56.000000000 +0000 +++ albert-0.11.1/README.md 2017-04-16 11:17:45.000000000 +0000 @@ -5,9 +5,3 @@ [![Telegram community chat](https://img.shields.io/badge/chat-telegram-0088cc.svg?style=flat)](https://telegram.me/albert_launcher_community) Access everything with virtually zero effort. Run applications, open files or their paths, open bookmarks in your browser, search the web, calculate things and a lot more. See the [docs](https://albertlauncher.github.io/docs) for more information. - -

- - Please wait… - -

diff -Nru albert-0.10.3/src/application/CMakeLists.txt albert-0.11.1/src/application/CMakeLists.txt --- albert-0.10.3/src/application/CMakeLists.txt 2017-04-02 16:54:56.000000000 +0000 +++ albert-0.11.1/src/application/CMakeLists.txt 2017-04-16 11:17:45.000000000 +0000 @@ -8,7 +8,7 @@ # Link target to libraries target_link_libraries(${PROJECT_NAME} albertcore) -# Set the RPATH so that libraries get found +# Set the RPATH for the library lookup set_target_properties(${PROJECT_NAME} PROPERTIES INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib/albert") # Install target diff -Nru albert-0.10.3/src/lib/albert/CMakeLists.txt albert-0.11.1/src/lib/albert/CMakeLists.txt --- albert-0.10.3/src/lib/albert/CMakeLists.txt 2017-04-02 16:54:56.000000000 +0000 +++ albert-0.11.1/src/lib/albert/CMakeLists.txt 2017-04-16 11:17:45.000000000 +0000 @@ -51,5 +51,8 @@ xdg ) +# Set the RPATH for the library lookup +set_target_properties(${PROJECT_NAME} PROPERTIES INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib/albert") + # Install target install(TARGETS ${PROJECT_NAME} LIBRARY DESTINATION lib/albert) diff -Nru albert-0.10.3/src/lib/albert/include/core_globals.h albert-0.11.1/src/lib/albert/include/core_globals.h --- albert-0.10.3/src/lib/albert/include/core_globals.h 2017-04-02 16:54:56.000000000 +0000 +++ albert-0.11.1/src/lib/albert/include/core_globals.h 2017-04-16 11:17:45.000000000 +0000 @@ -34,5 +34,5 @@ #define EXPORT_CORE IMPORT #endif -#define ALBERT_EXTENSION_IID "ExtensionInterface/v1.0" +#define ALBERT_EXTENSION_IID "ExtensionInterface/v1.0-alpha" diff -Nru albert-0.10.3/src/lib/albert/include/query.h albert-0.11.1/src/lib/albert/include/query.h --- albert-0.10.3/src/lib/albert/include/query.h 2017-04-02 16:54:56.000000000 +0000 +++ albert-0.11.1/src/lib/albert/include/query.h 2017-04-16 11:17:45.000000000 +0000 @@ -57,6 +57,9 @@ bool isValid() const; + bool isTriggered() const; + const QString &trigger() const; + void addMatch(std::shared_ptr item, short score = 0); void addMatches(std::vector,short>>::iterator begin, std::vector,short>>::iterator end); @@ -72,6 +75,8 @@ void invalidate(); + void setTrigger(const QString &trigger); + void setQueryHandlers(const std::set &); void setFallbacks(const std::vector> &); diff -Nru albert-0.10.3/src/lib/albert/include/queryhandler.h albert-0.11.1/src/lib/albert/include/queryhandler.h --- albert-0.10.3/src/lib/albert/include/queryhandler.h 2017-04-02 16:54:56.000000000 +0000 +++ albert-0.11.1/src/lib/albert/include/queryhandler.h 2017-04-16 11:17:45.000000000 +0000 @@ -32,11 +32,9 @@ const QString id; /** - * @brief The trigger that makes the plugin beeing run - * If runExclusice is set and the first word in the query matches one of - * this triggers the plugin is run exclusively. + * @brief The triggers that makes the plugin beeing run exclusice */ - virtual QString trigger() const { return QString(); } + virtual QStringList triggers() const { return QStringList(); } /** * @brief Session setup diff -Nru albert-0.10.3/src/lib/albert/src/albert/albert.cpp albert-0.11.1/src/lib/albert/src/albert/albert.cpp --- albert-0.10.3/src/lib/albert/src/albert/albert.cpp 2017-04-02 16:54:56.000000000 +0000 +++ albert-0.11.1/src/lib/albert/src/albert/albert.cpp 2017-04-16 11:17:45.000000000 +0000 @@ -68,7 +68,7 @@ app = new QApplication(argc, argv); app->setApplicationName("albert"); app->setApplicationDisplayName("Albert"); - app->setApplicationVersion("v0.10.3"); + app->setApplicationVersion("v0.11.1"); app->setQuitOnLastWindowClosed(false); QString icon = XdgIconLookup::iconPath("albert"); if ( icon.isEmpty() ) icon = ":app_icon"; @@ -76,6 +76,10 @@ QString socketPath = QStandardPaths::writableLocation(QStandardPaths::CacheLocation)+"/socket"; + // Set link color applicationwide to cyan + QPalette palette(qApp->palette()); + palette.setColor(QPalette::Link, QColor("#00CCCC")); + qApp->setPalette(palette); /* * PARSE COMMANDLINE @@ -152,35 +156,51 @@ QFile::rename(QString("%1/firstrun").arg(cacheLocation), QString("%1/firstrun").arg(dataLocation)); - QString lastUsedVersion; - QFile firstRunFile(QString("%1/firstrun").arg(dataLocation)); - if ( firstRunFile.exists() ) { - - //Try to open the first run file and read the version - if ( !firstRunFile.open(QIODevice::ReadOnly|QIODevice::Text) ) - qCritical() << qPrintable(QString("Could not open file %1: %2").arg(firstRunFile.fileName(), firstRunFile.errorString())); - QTextStream(&firstRunFile) >> lastUsedVersion; - firstRunFile.close(); - - } else { // This is the first run - - // Give the user a possibility to set a hotkey on first run + // If there is a firstRun file, rename it to lastVersion (since v0.11) + if ( QFile::exists(QString("%1/firstrun").arg(dataLocation)) ) + QFile::rename(QString("%1/firstrun").arg(dataLocation), + QString("%1/last_used_version").arg(dataLocation)); + + QFile file(QString("%1/last_used_version").arg(dataLocation)); + if ( file.exists() ) { + // Read last used version + if ( file.open(QIODevice::ReadOnly|QIODevice::Text) ) { + QString lastUsedVersion; + QTextStream(&file) >> lastUsedVersion; + file.close(); + + // Show newsbox in case of major version change + if ( app->applicationVersion().section('.', 1, 1) != lastUsedVersion.section('.', 1, 1) ){ + // Do whatever is neccessary on first run + QMessageBox(QMessageBox::Information, "First run", + QString("You are now using Albert %1. Albert is still in the alpha " + "stage. This means things may change unexpectedly. Check " + "the " + "news to see what changed.") + .arg(app->applicationVersion()) + ).exec(); + } + } + else + qCritical() << qPrintable(QString("Could not open file %1: %2,. Config migration may fail.") + .arg(file.fileName(), file.errorString())); + } else { + // Do whatever is neccessary on first run if ( QMessageBox(QMessageBox::Information, "First run", "Seems like this is the first time you run Albert. " "Most probably you want to set a hotkey to show " "Albert. Do you want to open the settings dialog?", QMessageBox::No|QMessageBox::Yes).exec() == QMessageBox::Yes ) showSettingsWhenInitialized = true; - } // Write the current version into the file - if ( firstRunFile.open(QIODevice::WriteOnly|QIODevice::Text) ) { - QTextStream out(&firstRunFile); + if ( file.open(QIODevice::WriteOnly|QIODevice::Text) ) { + QTextStream out(&file); out << app->applicationVersion(); - firstRunFile.close(); + file.close(); } else - qCritical() << qPrintable(QString("Could not open file %1: %2").arg(firstRunFile.fileName(), firstRunFile.errorString())); + qCritical() << qPrintable(QString("Could not open file %1: %2").arg(file.fileName(), file.errorString())); /* diff -Nru albert-0.10.3/src/lib/albert/src/albert/mainwindow/actionlist.cpp albert-0.11.1/src/lib/albert/src/albert/mainwindow/actionlist.cpp --- albert-0.10.3/src/lib/albert/src/albert/mainwindow/actionlist.cpp 2017-04-02 16:54:56.000000000 +0000 +++ albert-0.11.1/src/lib/albert/src/albert/mainwindow/actionlist.cpp 2017-04-16 11:17:45.000000000 +0000 @@ -65,6 +65,12 @@ // Draw text painter->setFont(option.font); QString text = QFontMetrics(option.font).elidedText(index.data(Qt::DisplayRole).toString(), option.textElideMode, option.rect.width()); - option.widget->style()->drawItemText(painter, option.rect, Qt::AlignCenter|Qt::AlignHCenter, option.palette, option.state & QStyle::State_Enabled, text, QPalette::WindowText); + option.widget->style()->drawItemText(painter, + option.rect, + Qt::AlignCenter|Qt::AlignHCenter, + option.palette, + option.state & QStyle::State_Enabled, + text, + (option.state & QStyle::State_Selected) ? QPalette::HighlightedText : QPalette::WindowText); painter->restore(); } diff -Nru albert-0.10.3/src/lib/albert/src/albert/mainwindow/proposallist.cpp albert-0.11.1/src/lib/albert/src/albert/mainwindow/proposallist.cpp --- albert-0.10.3/src/lib/albert/src/albert/mainwindow/proposallist.cpp 2017-04-02 16:54:56.000000000 +0000 +++ albert-0.11.1/src/lib/albert/src/albert/mainwindow/proposallist.cpp 2017-04-16 11:17:45.000000000 +0000 @@ -14,6 +14,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +#include #include #include #include @@ -120,6 +121,18 @@ } + +/** ***************************************************************************/ +void ProposalList::showEvent(QShowEvent *event) { + QWidget::showEvent(event); + if (qApp->keyboardModifiers() == Qt::MetaModifier) + delegate_->subTextRole = Qt::UserRole+101; + else + delegate_->subTextRole = Qt::ToolTipRole; +} + + + /** ***************************************************************************/ void ProposalList::ItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &options, const QModelIndex &index) const { @@ -192,14 +205,28 @@ // Draw display role painter->setFont(font1); - QString text = fontMetrics1.elidedText(index.data(Qt::DisplayRole).toString(), option.textElideMode, textRect.width()); - option.widget->style()->drawItemText(painter, textRect, option.displayAlignment, option.palette, option.state & QStyle::State_Enabled, text, QPalette::WindowText); - // painter->drawText(textRect, Qt::AlignTop|Qt::AlignLeft, text); + QString text = fontMetrics1.elidedText(index.data(Qt::DisplayRole).toString(), + option.textElideMode, + textRect.width()); + option.widget->style()->drawItemText(painter, + textRect, + option.displayAlignment, + option.palette, + option.state & QStyle::State_Enabled, + text, + (option.state & QStyle::State_Selected) ? QPalette::HighlightedText : QPalette::WindowText); // Draw tooltip role painter->setFont(font2); - text = fontMetrics2.elidedText(index.data(option.state.testFlag(QStyle::State_Selected)? subTextRole : Qt::ToolTipRole).toString(), option.textElideMode, subTextRect.width()); - painter->drawText(subTextRect , Qt::AlignBottom|Qt::AlignLeft, text); - + text = fontMetrics2.elidedText(index.data(option.state.testFlag(QStyle::State_Selected)? subTextRole : Qt::ToolTipRole).toString(), + option.textElideMode, + subTextRect.width()); + option.widget->style()->drawItemText(painter, + subTextRect, + Qt::AlignBottom|Qt::AlignLeft, + option.palette, + option.state & QStyle::State_Enabled, + text, + (option.state & QStyle::State_Selected) ? QPalette::HighlightedText : QPalette::WindowText); painter->restore(); } diff -Nru albert-0.10.3/src/lib/albert/src/albert/mainwindow/proposallist.h albert-0.11.1/src/lib/albert/src/albert/mainwindow/proposallist.h --- albert-0.10.3/src/lib/albert/src/albert/mainwindow/proposallist.h 2017-04-02 16:54:56.000000000 +0000 +++ albert-0.11.1/src/lib/albert/src/albert/mainwindow/proposallist.h 2017-04-16 11:17:45.000000000 +0000 @@ -34,6 +34,7 @@ private: bool eventFilter(QObject*, QEvent *event) override; + void showEvent(QShowEvent *event) override; ItemDelegate *delegate_; }; diff -Nru albert-0.10.3/src/lib/albert/src/albert/query.cpp albert-0.11.1/src/lib/albert/src/albert/query.cpp --- albert-0.10.3/src/lib/albert/src/albert/query.cpp 2017-04-02 16:54:56.000000000 +0000 +++ albert-0.11.1/src/lib/albert/src/albert/query.cpp 2017-04-16 11:17:45.000000000 +0000 @@ -46,6 +46,7 @@ Query *q; QString searchTerm; + QString trigger; bool isValid; Query::State state; @@ -60,11 +61,11 @@ mutable QMutex pendingResultsMutex; vector, short>> pendingResults; + QFuture> future; QFutureWatcher> futureWatcher; - /** ***************************************************************************/ void run() { @@ -94,14 +95,14 @@ void runSyncHandlers() { // Call onSyncHandlersFinsished when all handlers finished - futureWatcher.disconnect(); connect(&futureWatcher, &QFutureWatcher>::finished, this, &QueryPrivate::onSyncHandlersFinsished); // Run the handlers concurrently and measure the runtimes - futureWatcher.setFuture(QtConcurrent::mapped(syncHandlers.begin(), - syncHandlers.end(), - std::bind(&QueryPrivate::mappedFunction, this, std::placeholders::_1))); + future = QtConcurrent::mapped(syncHandlers.begin(), + syncHandlers.end(), + std::bind(&QueryPrivate::mappedFunction, this, std::placeholders::_1)); + futureWatcher.setFuture(future); } @@ -109,14 +110,17 @@ void runAsyncHandlers() { // Call onAsyncHandlersFinsished when all handlers finished - futureWatcher.disconnect(); + disconnect(&futureWatcher, &QFutureWatcher>::finished, + this, &QueryPrivate::onSyncHandlersFinsished); + connect(&futureWatcher, &QFutureWatcher>::finished, this, &QueryPrivate::onAsyncHandlersFinsished); // Run the handlers concurrently and measure the runtimes - futureWatcher.setFuture(QtConcurrent::mapped(asyncHandlers.begin(), - asyncHandlers.end(), - std::bind(&QueryPrivate::mappedFunction, this, std::placeholders::_1))); + future = QtConcurrent::mapped(asyncHandlers.begin(), + asyncHandlers.end(), + std::bind(&QueryPrivate::mappedFunction, this, std::placeholders::_1)); + futureWatcher.setFuture(future); // Insert pending results every 50 milliseconds connect(&fiftyMsTimer, &QTimer::timeout, this, &QueryPrivate::insertPendingResults); @@ -129,7 +133,7 @@ void onSyncHandlersFinsished() { // Save the runtimes of the current future - for ( auto it = futureWatcher.future().begin(); it != futureWatcher.future().end(); ++it ) + for ( auto it = future.begin(); it != future.end(); ++it ) runtimes.emplace(it->first->id, it->second); /* @@ -140,9 +144,9 @@ QMutexLocker lock(&pendingResultsMutex); // Sort the results - std::sort(pendingResults.begin(), - pendingResults.end(), - MatchCompare()); + std::stable_sort(pendingResults.begin(), + pendingResults.end(), + MatchCompare()); // Preallocate space in "results" to avoid multiple allocations results.reserve(results.size() + pendingResults.size()); @@ -168,7 +172,7 @@ void onAsyncHandlersFinsished() { // Save the runtimes of the current future - for ( auto it = futureWatcher.future().begin(); it != futureWatcher.future().end(); ++it ) + for ( auto it = future.begin(); it != future.end(); ++it ) runtimes.emplace(it->first->id, it->second); // Finally done @@ -352,6 +356,24 @@ /** ***************************************************************************/ +bool Core::Query::isTriggered() const { + return !d->trigger.isEmpty(); +} + + +/** ***************************************************************************/ +const QString &Core::Query::trigger() const { + return d->trigger; +} + + +/** ***************************************************************************/ +void Core::Query::setTrigger(const QString &trigger) { + d->trigger = trigger; +} + + +/** ***************************************************************************/ void Core::Query::addMatch(shared_ptr item, short score) { if ( d->isValid ) { d->pendingResultsMutex.lock(); @@ -391,6 +413,7 @@ d->isValid = false; } + /** ***************************************************************************/ void Core::Query::setQueryHandlers(const set &queryHandlers) { diff -Nru albert-0.10.3/src/lib/albert/src/albert/querymanager.cpp albert-0.11.1/src/lib/albert/src/albert/querymanager.cpp --- albert-0.10.3/src/lib/albert/src/albert/querymanager.cpp 2017-04-02 16:54:56.000000000 +0000 +++ albert-0.11.1/src/lib/albert/src/albert/querymanager.cpp 2017-04-16 11:17:45.000000000 +0000 @@ -117,6 +117,30 @@ return; } + // Start query + currentQuery_ = new Query; + currentQuery_->setSearchTerm(searchTerm); + connect(currentQuery_, &Query::resultsReady, this, &QueryManager::resultsReady); + + // Run with a single handler if the trigger matches + const set availableHandlers = extensionManager_->objectsByType(); + for ( QueryHandler *handler : availableHandlers ) { + for ( const QString& trigger : handler->triggers() ) { + if ( !trigger.isEmpty() && searchTerm.startsWith(trigger) ) { + currentQuery_->setTrigger(trigger); + currentQuery_->setQueryHandlers({handler}); + currentQuery_->run(); + return; + } + } + } + + // Else run all handlers + set handlers; + for ( QueryHandler *handler : availableHandlers ) + handlers.insert(handler); + currentQuery_->setQueryHandlers(handlers); + // Get fallbacks vector> fallbacks; for ( FallbackProvider *extension : extensionManager_->objectsByType() ) { @@ -126,24 +150,6 @@ std::make_move_iterator(tmpFallbacks.end())); } - // Determine query handlers - const set allHandlers = extensionManager_->objectsByType(); - set actualHandlers; - for ( QueryHandler *handler : allHandlers ) - if ( !handler->trigger().isEmpty() && searchTerm.startsWith(handler->trigger()) ) - actualHandlers.insert(handler); - - if (actualHandlers.empty()) - for ( QueryHandler *handler : allHandlers ) - if ( handler->trigger().isEmpty() ) - actualHandlers.insert(handler); - - - // Start query - currentQuery_ = new Query; - connect(currentQuery_, &Query::resultsReady, this, &QueryManager::resultsReady); - currentQuery_->setSearchTerm(searchTerm); - currentQuery_->setQueryHandlers(actualHandlers); currentQuery_->setFallbacks(fallbacks); currentQuery_->run(); } diff -Nru albert-0.10.3/src/lib/albert/src/albert/settingswidget/settingswidget.cpp albert-0.11.1/src/lib/albert/src/albert/settingswidget/settingswidget.cpp --- albert-0.10.3/src/lib/albert/src/albert/settingswidget/settingswidget.cpp 2017-04-02 16:54:56.000000000 +0000 +++ albert-0.11.1/src/lib/albert/src/albert/settingswidget/settingswidget.cpp 2017-04-16 11:17:45.000000000 +0000 @@ -136,21 +136,20 @@ // Available terms std::vector> terms { - {"XTerm", "xterm -e"}, - {"UXTerm", "uxterm -e"}, - {"urxvt", "urxvt -e"}, - {"Terminator", "terminator -x"}, - {"LXTerminal", "lxterminal -e"}, - {"Konsole", "konsole -e"}, - {"Gnome Terminal", "gnome-terminal -x"}, - {"XFCE-Terminal", "xfce4-terminal -x"}, {"Cool Retro Term", "cool-retro-term -e"}, + {"Gnome Terminal", "gnome-terminal -x"}, + {"Konsole", "konsole -e"}, + {"LXTerminal", "lxterminal -e"}, + {"Mate-Termial", "mate-terminal -x"}, {"RoxTerm", "roxterm -x"}, - {"Mate-Termial", "mate-terminal -x"} + {"Terminator", "terminator -x"}, + {"urxvt", "urxvt -e"}, + {"UXTerm", "uxterm -e"}, + {"XFCE-Terminal", "xfce4-terminal -x"}, + {"XTerm", "xterm -e"} }; // Fill checkbox - ui.comboBox_term->addItem(tr("Custom")); for ( ulong i = 0; i < terms.size(); ++i ) { if ( !QStandardPaths::findExecutable(terms[i].second.split(' ').first()).isEmpty() ){ ui.comboBox_term->addItem(terms[i].first, terms[i].second); @@ -158,18 +157,19 @@ ui.comboBox_term->setCurrentIndex(static_cast(ui.comboBox_term->count()-1)); } } - ui.lineEdit_term->setText(terminalCommand); - ui.lineEdit_term->setVisible(ui.comboBox_term->currentIndex() == 0); + ui.comboBox_term->insertSeparator(ui.comboBox_term->count()); + ui.comboBox_term->addItem(tr("Custom")); + ui.lineEdit_term->setText(terminalCommand); + ui.lineEdit_term->setEnabled(ui.comboBox_term->currentIndex() == ui.comboBox_term->count()-1); connect(ui.comboBox_term, static_cast(&QComboBox::currentIndexChanged), [this](int index){ - if ( index == 0 ) - ui.lineEdit_term->setText(terminalCommand); - else { + if ( index != ui.comboBox_term->count()-1) { terminalCommand = ui.comboBox_term->currentData(Qt::UserRole).toString(); QSettings(qApp->applicationName()).setValue(CFG_TERM, terminalCommand); } - ui.lineEdit_term->setVisible(index == 0); + ui.lineEdit_term->setEnabled(index == ui.comboBox_term->count()-1); + ui.lineEdit_term->setText(terminalCommand); }); connect(ui.lineEdit_term, &QLineEdit::textEdited, [](QString str){ diff -Nru albert-0.10.3/src/lib/albert/src/albert/settingswidget/settingswidget.ui albert-0.11.1/src/lib/albert/src/albert/settingswidget/settingswidget.ui --- albert-0.10.3/src/lib/albert/src/albert/settingswidget/settingswidget.ui 2017-04-02 16:54:56.000000000 +0000 +++ albert-0.11.1/src/lib/albert/src/albert/settingswidget/settingswidget.ui 2017-04-16 11:17:45.000000000 +0000 @@ -566,7 +566,7 @@ - :/app_icon + :/app_icon false @@ -633,7 +633,7 @@ - + diff -Nru albert-0.10.3/src/plugins/CMakeLists.txt albert-0.11.1/src/plugins/CMakeLists.txt --- albert-0.10.3/src/plugins/CMakeLists.txt 2017-04-02 16:54:56.000000000 +0000 +++ albert-0.11.1/src/plugins/CMakeLists.txt 2017-04-16 11:17:45.000000000 +0000 @@ -2,6 +2,9 @@ set(CMAKE_CXX_VISIBILITY_PRESET hidden) set(CMAKE_VISIBILITY_INLINES_HIDDEN 1) +# Set the RPATH for the library lookup +set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib/albert") + add_subdirectory(applications) add_subdirectory(calculator) add_subdirectory(chromebookmarks) diff -Nru albert-0.10.3/src/plugins/debug/src/main.cpp albert-0.11.1/src/plugins/debug/src/main.cpp --- albert-0.10.3/src/plugins/debug/src/main.cpp 2017-04-02 16:54:56.000000000 +0000 +++ albert-0.11.1/src/plugins/debug/src/main.cpp 2017-04-16 11:17:45.000000000 +0000 @@ -73,7 +73,14 @@ /** ***************************************************************************/ -QString Debug::Extension::trigger() const { +QStringList Debug::Extension::triggers() const { + return {d->trigger}; +} + + + +/** ***************************************************************************/ +const QString& Debug::Extension::trigger() const { return d->trigger; } @@ -81,7 +88,9 @@ /** ***************************************************************************/ void Debug::Extension::handleQuery(Core::Query * query) { - if (!query->isValid()) + + // This extension must run only triggered + if ( !query->isTriggered() ) return; for (int i = 0 ; i < d->count; ++i){ diff -Nru albert-0.10.3/src/plugins/debug/src/main.h albert-0.11.1/src/plugins/debug/src/main.h --- albert-0.10.3/src/plugins/debug/src/main.h 2017-04-02 16:54:56.000000000 +0000 +++ albert-0.11.1/src/plugins/debug/src/main.h 2017-04-16 11:17:45.000000000 +0000 @@ -44,7 +44,7 @@ QString name() const override { return "Debug"; } QWidget *widget(QWidget *parent = nullptr) override; - QString trigger() const override; + QStringList triggers() const override; void handleQuery(Core::Query * query) override; bool isLongRunning() const override { return true; } @@ -61,6 +61,7 @@ int delay() const; void setDelay(const int &delay); + const QString& trigger() const; void setTrigger(const QString &trigger); private: diff -Nru albert-0.10.3/src/plugins/externalextensions/src/externalextension.cpp albert-0.11.1/src/plugins/externalextensions/src/externalextension.cpp --- albert-0.10.3/src/plugins/externalextensions/src/externalextension.cpp 2017-04-02 16:54:56.000000000 +0000 +++ albert-0.11.1/src/plugins/externalextensions/src/externalextension.cpp 2017-04-16 11:17:45.000000000 +0000 @@ -302,6 +302,10 @@ /** ***************************************************************************/ void ExternalExtensions::ExternalExtension::handleQuery(Query* query) { + // External extension must run only when triggered, since they are to ressource heavy + if ( !query->isTriggered() ) + return; + // Never run the extension concurrent QMutexLocker lock (&processMutex_); QString errorString; @@ -361,6 +365,7 @@ standardItem = std::make_shared(object["id"].toString()); standardItem->setText(object["name"].toString()); standardItem->setSubtext(object["description"].toString()); + standardItem->setCompletionString(object["completion"].toString()); QString iconPath; if ( !(iconPath = XdgIconLookup::iconPath(object["icon"].toString())).isNull() ) standardItem->setIconPath(iconPath); diff -Nru albert-0.10.3/src/plugins/externalextensions/src/externalextension.h albert-0.11.1/src/plugins/externalextensions/src/externalextension.h --- albert-0.10.3/src/plugins/externalextensions/src/externalextension.h 2017-04-02 16:54:56.000000000 +0000 +++ albert-0.11.1/src/plugins/externalextensions/src/externalextension.h 2017-04-16 11:17:45.000000000 +0000 @@ -35,7 +35,7 @@ * Implementation of extension interface */ - QString trigger() const override { return trigger_; } + QStringList triggers() const override { return {trigger_}; } void setupSession() override; void teardownSession() override; void handleQuery(Core::Query *query) override; diff -Nru albert-0.10.3/src/plugins/externalextensions/src/externalextensionmodel.cpp albert-0.11.1/src/plugins/externalextensions/src/externalextensionmodel.cpp --- albert-0.10.3/src/plugins/externalextensions/src/externalextensionmodel.cpp 2017-04-02 16:54:56.000000000 +0000 +++ albert-0.11.1/src/plugins/externalextensions/src/externalextensionmodel.cpp 2017-04-16 11:17:45.000000000 +0000 @@ -89,7 +89,7 @@ case Qt::DisplayRole: { switch (static_cast
(index.column())) { case Section::Name: return externalExtensions_[index.row()]->name(); - case Section::Trigger: return externalExtensions_[index.row()]->trigger(); + case Section::Trigger: return externalExtensions_[index.row()]->triggers()[0] ; case Section::Path: return externalExtensions_[index.row()]->path(); default: return QVariant(); } @@ -97,7 +97,7 @@ case Qt::EditRole: { switch (static_cast
(index.column())) { case Section::Name: return externalExtensions_[index.row()]->name(); - case Section::Trigger: return externalExtensions_[index.row()]->trigger(); + case Section::Trigger: return externalExtensions_[index.row()]->triggers()[0]; case Section::Path: return externalExtensions_[index.row()]->path(); default: return QVariant(); } diff -Nru albert-0.10.3/src/plugins/files/CMakeLists.txt albert-0.11.1/src/plugins/files/CMakeLists.txt --- albert-0.10.3/src/plugins/files/CMakeLists.txt 2017-04-02 16:54:56.000000000 +0000 +++ albert-0.11.1/src/plugins/files/CMakeLists.txt 2017-04-16 11:17:45.000000000 +0000 @@ -15,7 +15,6 @@ qt5_wrap_ui(UI forms/configwidget.ui - forms/mimetypechooser.ui forms/mimetypedialog.ui ) diff -Nru albert-0.10.3/src/plugins/files/forms/configwidget.ui albert-0.11.1/src/plugins/files/forms/configwidget.ui --- albert-0.10.3/src/plugins/files/forms/configwidget.ui 2017-04-02 16:54:56.000000000 +0000 +++ albert-0.11.1/src/plugins/files/forms/configwidget.ui 2017-04-16 11:17:45.000000000 +0000 @@ -2,108 +2,142 @@ Files::ConfigWidget - + - - - Paths - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - true + + + + + Paths + + + + 0 + + + 0 - - true + + 0 - - true + + 0 - - - - - - - Add + + + true - - - - - - Remove + + true - - - Restore - - + + + + + + 0 + 0 + + + + + .. + + + + + + + + 0 + 0 + + + + + .. + + + + + + + Restore + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + - + - Update index + - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - + + - + - + - Indexed types + Scan interval - - - 0 - - - 0 - - - 0 - + - 0 + 5 + + + + 0 + + + 1440 + + + 5 + + + 60 + + + + + + + minutes + + + + + + + + + + Indexed MIME types + + @@ -132,20 +166,17 @@ - - - - false - + + - Advanced + Audio - - + + - Audio + Advanced @@ -153,40 +184,11 @@ - - - Qt::Vertical - - - - 0 - 0 - - - - - - - - - Misc settings - - 0 - - - 0 - - - 0 - - - 0 - @@ -212,103 +214,46 @@ - + Qt::Vertical - 0 - 0 + 20 + 40 - - - - - - - Scan interval - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 0 - - - 1440 - - - 5 - - - 60 - - - - - - - minutes - - - - - - - - - - Qt::Vertical - - - - 0 - 0 - - - + + + + + Qt::Horizontal + + + + 0 + 0 + + + + + + + + Update index + + + + - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - diff -Nru albert-0.10.3/src/plugins/files/forms/mimetypechooser.ui albert-0.11.1/src/plugins/files/forms/mimetypechooser.ui --- albert-0.10.3/src/plugins/files/forms/mimetypechooser.ui 2017-04-02 16:54:56.000000000 +0000 +++ albert-0.11.1/src/plugins/files/forms/mimetypechooser.ui 1970-01-01 00:00:00.000000000 +0000 @@ -1,82 +0,0 @@ - - - Files::MimeTypeChooser - - - - 0 - 0 - 256 - 256 - - - - Dialog - - - - 6 - - - 4 - - - 4 - - - 4 - - - 4 - - - - - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - - buttonBox - accepted() - Files::MimeTypeChooser - accept() - - - 248 - 254 - - - 157 - 274 - - - - - buttonBox - rejected() - Files::MimeTypeChooser - reject() - - - 316 - 260 - - - 286 - 274 - - - - - diff -Nru albert-0.10.3/src/plugins/files/forms/mimetypedialog.ui albert-0.11.1/src/plugins/files/forms/mimetypedialog.ui --- albert-0.10.3/src/plugins/files/forms/mimetypedialog.ui 2017-04-02 16:54:56.000000000 +0000 +++ albert-0.11.1/src/plugins/files/forms/mimetypedialog.ui 2017-04-16 11:17:45.000000000 +0000 @@ -2,20 +2,6 @@ Files::MimeTypeDialog - - - 0 - 0 - 480 - 256 - - - - - 480 - 256 - - Dialog @@ -35,56 +21,89 @@ - - - QAbstractItemView::EditKeyPressed - - - QAbstractItemView::DropOnly - - - true - - - true - - - - - + - - - Add + + + Qt::ScrollBarAlwaysOn + + + QAbstractItemView::EditKeyPressed + + + QAbstractItemView::DropOnly + + + true - - - Remove + + + Filter for the mimetypes… + + + + - - - - 0 - 0 - - + - <html><head/><body><p align="justify"><span style=" font-size:8pt; color:#a3a3a3;">Drop files into the list to add their mimetypes or choose a mimetype from the complete list using the &quot;Add mimetype&quot; button.</span></p></body></html> + > - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + .. - - true + + + + + + + + + + Drop files into the list to add their mimetypes or choose a mimetype from the complete list using the "Add mimetype" button. + + + Qt::ScrollBarAlwaysOn + + + + + + <html><head/><body><p><span style=" color:#808080;">This is the list of patterns that is used to filter the indexed files by matching their mime type.</span></p></body></html> + + + true + + + + + + + + .. + + + + + + + + .. + + + + + @@ -92,7 +111,7 @@ - QDialogButtonBox::Abort|QDialogButtonBox::Ok + QDialogButtonBox::Cancel|QDialogButtonBox::Ok diff -Nru albert-0.10.3/src/plugins/files/src/configwidget.cpp albert-0.11.1/src/plugins/files/src/configwidget.cpp --- albert-0.10.3/src/plugins/files/src/configwidget.cpp 2017-04-02 16:54:56.000000000 +0000 +++ albert-0.11.1/src/plugins/files/src/configwidget.cpp 2017-04-16 11:17:45.000000000 +0000 @@ -14,64 +14,233 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -#include "configwidget.h" #include #include -#include -#include "mimetypechooser.h" +#include +#include "configwidget.h" +#include "main.h" +#include "mimetypedialog.h" /** ***************************************************************************/ -Files::ConfigWidget::ConfigWidget(QWidget *parent) : QWidget(parent) { +Files::ConfigWidget::ConfigWidget(Extension *_extension, QWidget *_parent) + : QWidget(_parent), extension(_extension) { ui.setupUi(this); - connect(ui.pushButton_add, &QPushButton::clicked, this, &ConfigWidget::onButton_PathAdd); - connect(ui.pushButton_remove, &QPushButton::clicked, this, &ConfigWidget::onButton_PathRemove); - connect(ui.pushButton_advanced, &QPushButton::clicked, this, &ConfigWidget::onButton_Advanced); - // TODO: Implement mime filter - ui.pushButton_advanced->hide(); -} - - - -/** ***************************************************************************/ -Files::ConfigWidget::~ConfigWidget() { - -} - -/** ***************************************************************************/ -void Files::ConfigWidget::setInfo(const QString &info) { - ui.label_statusbar->setText(ui.label_statusbar->fontMetrics().elidedText(info, Qt::ElideMiddle, ui.label_statusbar->width())); -} - - - -/** ***************************************************************************/ -void Files::ConfigWidget::onButton_PathAdd() { - QString path = QFileDialog::getExistingDirectory( - this, - tr("Choose path"), - QStandardPaths::writableLocation(QStandardPaths::HomeLocation)); + // Paths + QStringListModel *pathsModel = new QStringListModel(this); + pathsModel->setStringList(extension->paths()); + ui.listView_paths->setModel(pathsModel); + + connect(pathsModel, &QStringListModel::dataChanged, + [=](){ extension->setPaths(pathsModel->stringList()); }); + + connect(pathsModel, &QStringListModel::rowsInserted, + [=](){ extension->setPaths(pathsModel->stringList()); }); + + connect(pathsModel, &QStringListModel::rowsRemoved, + [=](){ extension->setPaths(pathsModel->stringList()); }); + + // Buttons + connect(ui.pushButton_add, &QPushButton::clicked, [=](){ + QString path = QFileDialog::getExistingDirectory( + this, + tr("Choose path"), + QStandardPaths::writableLocation(QStandardPaths::HomeLocation)); + + if(path.isEmpty()) + return; + + if ( pathsModel->match(pathsModel->index(0, 0), Qt::DisplayRole, + QVariant::fromValue(path)).isEmpty() ) { + pathsModel->insertRow(pathsModel->rowCount()); + pathsModel->setData(pathsModel->index(pathsModel->rowCount()-1,0), path); + } + }); + + connect(ui.pushButton_remove, &QPushButton::clicked, [=](){ + if ( !ui.listView_paths->currentIndex().isValid() ) + return; + pathsModel->removeRow(ui.listView_paths->currentIndex().row()); + }); + + connect(ui.pushButton_update, &QPushButton::clicked, + extension, &Extension::updateIndex); + + connect(ui.pushButton_restore, &QPushButton::clicked, + extension, &Extension::restorePaths); + + /* + * Initialize the indexing options + */ + + ui.checkBox_hidden->setChecked(extension->indexHidden()); + connect(ui.checkBox_hidden, &QCheckBox::toggled, extension, &Extension::setIndexHidden); + + ui.checkBox_followSymlinks->setChecked(extension->followSymlinks()); + connect(ui.checkBox_followSymlinks, &QCheckBox::toggled, extension, &Extension::setFollowSymlinks); + + ui.checkBox_fuzzy->setChecked(extension->fuzzy()); + connect(ui.checkBox_fuzzy, &QCheckBox::toggled, extension, &Extension::setFuzzy); + + ui.spinBox_interval->setValue(static_cast(extension->scanInterval())); + connect(ui.spinBox_interval, static_cast(&QSpinBox::valueChanged), + extension, &Extension::setScanInterval); + + /* + * Initialize the mime options + */ + + if (extension->filters().contains("audio/*")) + ui.checkBox_audio->setCheckState(Qt::Checked); + else if (std::any_of(extension->filters().begin(), extension->filters().end(), + [](const QString & str){ return str.startsWith("audio/"); })) + ui.checkBox_audio->setCheckState(Qt::PartiallyChecked); + else + ui.checkBox_audio->setCheckState(Qt::Unchecked); + + if (extension->filters().contains("video/*")) + ui.checkBox_video->setCheckState(Qt::Checked); + else if (std::any_of(extension->filters().begin(), extension->filters().end(), + [](const QString & str){ return str.startsWith("video/"); })) + ui.checkBox_video->setCheckState(Qt::PartiallyChecked); + else + ui.checkBox_video->setCheckState(Qt::Unchecked); + + if (extension->filters().contains("image/*")) + ui.checkBox_image->setCheckState(Qt::Checked); + else if (std::any_of(extension->filters().begin(), extension->filters().end(), + [](const QString & str){ return str.startsWith("image/"); })) + ui.checkBox_image->setCheckState(Qt::PartiallyChecked); + else + ui.checkBox_image->setCheckState(Qt::Unchecked); + + if (extension->filters().contains("application/*")) + ui.checkBox_docs->setCheckState(Qt::Checked); + else if (std::any_of(extension->filters().begin(), extension->filters().end(), + [](const QString & str){ return str.startsWith("application/"); })) + ui.checkBox_docs->setCheckState(Qt::PartiallyChecked); + else + ui.checkBox_docs->setCheckState(Qt::Unchecked); + + if (extension->filters().contains("inode/directory")) + ui.checkBox_dirs->setCheckState(Qt::Checked); + else + ui.checkBox_dirs->setCheckState(Qt::Unchecked); + + /* + * Set the actions for checking the mime options + */ + + connect(ui.checkBox_audio, &QCheckBox::clicked, extension, [this]() { + ui.checkBox_audio->setTristate(false); + QStringList filters = extension->filters(); + filters.erase(std::remove_if(filters.begin(), filters.end(), + [](const QString &str){ return str.startsWith("audio/"); }), + filters.end()); + if (ui.checkBox_audio->checkState() == Qt::Checked) + filters.push_back("audio/*"); + extension->setFilters(filters); + }); + + connect(ui.checkBox_video, &QCheckBox::clicked, extension, [this]() { + ui.checkBox_video->setTristate(false); + QStringList filters = extension->filters(); + filters.erase(std::remove_if(filters.begin(), filters.end(), + [](const QString &str){ return str.startsWith("video/"); }), + filters.end()); + if (ui.checkBox_video->checkState() == Qt::Checked) + filters.push_back("video/*"); + extension->setFilters(filters); + }); + + connect(ui.checkBox_image, &QCheckBox::clicked, extension, [this]() { + ui.checkBox_image->setTristate(false); + QStringList filters = extension->filters(); + filters.erase(std::remove_if(filters.begin(), filters.end(), + [](const QString &str){ return str.startsWith("image/"); }), + filters.end()); + if (ui.checkBox_image->checkState() == Qt::Checked) + filters.push_back("image/*"); + extension->setFilters(filters); + }); + + connect(ui.checkBox_docs, &QCheckBox::clicked, extension, [this]() { + ui.checkBox_docs->setTristate(false); + QStringList filters = extension->filters(); + filters.erase(std::remove_if(filters.begin(), filters.end(), + [](const QString &str){ return str.startsWith("application/"); }), + filters.end()); + if (ui.checkBox_docs->checkState() == Qt::Checked) + filters.push_back("application/*"); + extension->setFilters(filters); + }); + + connect(ui.checkBox_dirs, &QCheckBox::toggled, extension, [=](bool checked){ + QStringList filters = extension->filters(); + filters.removeAll("inode/directory"); + if (checked) + filters.push_back("inode/directory"); + extension->setFilters(filters); + }); + + // The advanced button action + connect(ui.pushButton_advanced, &QPushButton::clicked, [=](){ + + MimeTypeDialog dialog(extension->filters(), this); + dialog.setWindowModality(Qt::WindowModal); + if ( dialog.exec() ) { + + // If the dialog has been accepted, update extension and checkboxes + extension->setFilters(dialog.filters()); + + // Set the shortcuts + if (extension->filters().contains("audio/*")) + ui.checkBox_audio->setCheckState(Qt::Checked); + else if (std::any_of(extension->filters().begin(), extension->filters().end(), + [](const QString & str){ return str.startsWith("audio/"); })) + ui.checkBox_audio->setCheckState(Qt::PartiallyChecked); + else + ui.checkBox_audio->setCheckState(Qt::Unchecked); + + if (extension->filters().contains("video/*")) + ui.checkBox_video->setCheckState(Qt::Checked); + else if (std::any_of(extension->filters().begin(), extension->filters().end(), + [](const QString & str){ return str.startsWith("video/"); })) + ui.checkBox_video->setCheckState(Qt::PartiallyChecked); + else + ui.checkBox_video->setCheckState(Qt::Unchecked); + + if (extension->filters().contains("image/*")) + ui.checkBox_image->setCheckState(Qt::Checked); + else if (std::any_of(extension->filters().begin(), extension->filters().end(), + [](const QString & str){ return str.startsWith("image/"); })) + ui.checkBox_image->setCheckState(Qt::PartiallyChecked); + else + ui.checkBox_image->setCheckState(Qt::Unchecked); + + if (extension->filters().contains("application/*")) + ui.checkBox_docs->setCheckState(Qt::Checked); + else if (std::any_of(extension->filters().begin(), extension->filters().end(), + [](const QString & str){ return str.startsWith("application/"); })) + ui.checkBox_docs->setCheckState(Qt::PartiallyChecked); + else + ui.checkBox_docs->setCheckState(Qt::Unchecked); + + if (extension->filters().contains("inode/directory")) + ui.checkBox_dirs->setCheckState(Qt::Checked); + else + ui.checkBox_dirs->setCheckState(Qt::Unchecked); + } + }); - if(path.isEmpty()) - return; - - emit requestAddPath(path); + // Status bar + connect(extension, &Extension::statusInfo, ui.label_statusbar, &QLabel::setText); } /** ***************************************************************************/ -void Files::ConfigWidget::onButton_PathRemove() { - if (ui.listWidget_paths->currentItem() == nullptr) - return; - emit requestRemovePath(ui.listWidget_paths->currentItem()->text()); -} - - +Files::ConfigWidget::~ConfigWidget() { -/** ***************************************************************************/ -void Files::ConfigWidget::onButton_Advanced() { - MimeTypeChooser *c = new MimeTypeChooser; - c->show(); } diff -Nru albert-0.10.3/src/plugins/files/src/configwidget.h albert-0.11.1/src/plugins/files/src/configwidget.h --- albert-0.10.3/src/plugins/files/src/configwidget.h 2017-04-02 16:54:56.000000000 +0000 +++ albert-0.11.1/src/plugins/files/src/configwidget.h 2017-04-16 11:17:45.000000000 +0000 @@ -21,27 +21,28 @@ #include "ui_configwidget.h" namespace Files { + +class Extension; + class ConfigWidget final : public QWidget { Q_OBJECT -public: - explicit ConfigWidget(QWidget *parent = 0); - ~ConfigWidget(); - void setInfo(const QString &); +public: - Ui::ConfigWidget ui; + explicit ConfigWidget(Extension *ext, QWidget *parent = 0); + ~ConfigWidget(); private: - void onButton_PathAdd(); - void onButton_PathRemove(); - void onButton_RestorePaths(); - void onButton_Advanced(); + Extension *extension; + Ui::ConfigWidget ui; signals: + void requestAddPath(const QString&); void requestRemovePath(const QString&); }; + } diff -Nru albert-0.10.3/src/plugins/files/src/main.cpp albert-0.11.1/src/plugins/files/src/main.cpp --- albert-0.10.3/src/plugins/files/src/main.cpp 2017-04-02 16:54:56.000000000 +0000 +++ albert-0.11.1/src/plugins/files/src/main.cpp 2017-04-16 11:17:45.000000000 +0000 @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -45,18 +46,10 @@ namespace { const char* CFG_PATHS = "paths"; +const char* CFG_FILTERS = "filters"; +const QStringList DEF_FILTERS = { "inode/directory", "application/*" }; const char* CFG_FUZZY = "fuzzy"; const bool DEF_FUZZY = false; -const char* CFG_INDEX_AUDIO = "indexaudio"; -const bool DEF_INDEX_AUDIO = true; -const char* CFG_INDEX_VIDEO = "indexvideo"; -const bool DEF_INDEX_VIDEO = true; -const char* CFG_INDEX_IMAGE = "indeximage"; -const bool DEF_INDEX_IMAGE = true; -const char* CFG_INDEX_DOC = "indexdocs"; -const bool DEF_INDEX_DOC = true; -const char* CFG_INDEX_DIR = "indexdirs"; -const bool DEF_INDEX_DIR = true; const char* CFG_INDEX_HIDDEN = "indexhidden"; const bool DEF_INDEX_HIDDEN = false; const char* CFG_FOLLOW_SYMLINKS = "follow_symlinks"; @@ -65,6 +58,13 @@ const uint DEF_SCAN_INTERVAL = 60; const char* IGNOREFILE = ".albertignore"; +struct IndexSettings { + QStringList rootDirs; + QStringList filters; + bool indexHidden; + bool followSymlinks; +}; + } @@ -81,7 +81,6 @@ Extension *q; QPointer widget; - QStringList rootDirs; vector> index; Core::OfflineIndex offlineIndex; @@ -90,18 +89,11 @@ bool abort; bool rerun; - // Index Properties - bool indexAudio; - bool indexVideo; - bool indexImage; - bool indexDocs; - bool indexDirs; - bool indexHidden; - bool followSymlinks; + IndexSettings indexSettings; void finishIndexing(); void startIndexing(); - vector> indexFiles() const; + vector> indexFiles(const IndexSettings &indexSettings) const; }; @@ -127,7 +119,7 @@ indexIntervalTimer.start(); // Run the indexer thread - futureWatcher.setFuture(QtConcurrent::run(this, &FilesPrivate::indexFiles)); + futureWatcher.setFuture(QtConcurrent::run(this, &FilesPrivate::indexFiles, indexSettings)); // Notification qDebug() << "Start indexing files."; @@ -165,55 +157,47 @@ /** ***************************************************************************/ -vector> Files::FilesPrivate::indexFiles() const { +vector> +Files::FilesPrivate::indexFiles(const IndexSettings &indexSettings) const { // Get a new index std::vector> newIndex; std::set indexedDirs; QMimeDatabase mimeDatabase; + std::vector mimeFilters; + for (const QString &re : indexSettings.filters) + mimeFilters.emplace_back(re, Qt::CaseInsensitive, QRegExp::Wildcard); // Prepare the iterator properties QDir::Filters filters = QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot; - if (indexHidden) + if (indexSettings.indexHidden) filters |= QDir::Hidden; // Anonymous function that implemnents the index recursion - std::function indexRecursion = - [this, &mimeDatabase, &newIndex, &indexedDirs, &filters, &indexRecursion](const QFileInfo& fileInfo){ + std::function indexRecursion = [&](const QFileInfo& fileInfo){ if (abort) return; const QString canonicalPath = fileInfo.canonicalFilePath(); + const QMimeType mimetype = mimeDatabase.mimeTypeForFile(canonicalPath); + const QString mimeName = mimetype.name(); - if (fileInfo.isFile()) { + // If the file matches the index options, index it + if ( std::any_of(mimeFilters.begin(), mimeFilters.end(), + [&](const QRegExp &re){ return re.exactMatch(mimeName); }) ) + newIndex.push_back(std::make_shared(canonicalPath, mimetype)); - // If the file matches the index options, index it - QMimeType mimetype = mimeDatabase.mimeTypeForFile(canonicalPath); - const QString mimeName = mimetype.name(); - if ((indexAudio && mimeName.startsWith("audio")) - ||(indexVideo && mimeName.startsWith("video")) - ||(indexImage && mimeName.startsWith("image")) - ||(indexDocs && - (mimeName.startsWith("application") || mimeName.startsWith("text")))) { - newIndex.push_back(std::make_shared(canonicalPath, mimetype)); - } - } else if (fileInfo.isDir()) { + if (fileInfo.isDir()) { emit q->statusInfo(QString("Indexing %1.").arg(canonicalPath)); // Skip if this dir has already been indexed - if (indexedDirs.find(canonicalPath)!=indexedDirs.end()) + if ( indexedDirs.find(canonicalPath) != indexedDirs.end() ) return; // Remember that this dir has been indexed to avoid loops indexedDirs.insert(canonicalPath); - // If the dir matches the index options, index it - if (indexDirs) { - QMimeType mimetype = mimeDatabase.mimeTypeForFile(canonicalPath); - newIndex.push_back(std::make_shared(canonicalPath, mimetype)); - } - // Ignore ignorefile by default std::vector ignores; ignores.push_back(QRegExp(IGNOREFILE, Qt::CaseSensitive, QRegExp::Wildcard)); @@ -240,7 +224,7 @@ continue; // Skip if this file is a symlink and we shoud skip symlinks - if (fileInfo.isSymLink() && !followSymlinks) + if (fileInfo.isSymLink() && !indexSettings.followSymlinks) continue; // Index this file @@ -250,7 +234,7 @@ }; // Start the indexing - for (const QString &rootDir : rootDirs) { + for (const QString &rootDir : indexSettings.rootDirs) { indexRecursion(QFileInfo(rootDir)); if (abort) return vector>(); } @@ -282,17 +266,13 @@ // Load settings QSettings s(qApp->applicationName()); s.beginGroup(Core::Extension::id); - d->indexAudio = s.value(CFG_INDEX_AUDIO, DEF_INDEX_AUDIO).toBool(); - d->indexVideo = s.value(CFG_INDEX_VIDEO, DEF_INDEX_VIDEO).toBool(); - d->indexImage = s.value(CFG_INDEX_IMAGE, DEF_INDEX_IMAGE).toBool(); - d->indexDocs = s.value(CFG_INDEX_DOC, DEF_INDEX_DOC).toBool(); - d->indexDirs = s.value(CFG_INDEX_DIR, DEF_INDEX_DIR).toBool(); - d->indexHidden = s.value(CFG_INDEX_HIDDEN, DEF_INDEX_HIDDEN).toBool(); - d->followSymlinks = s.value(CFG_FOLLOW_SYMLINKS, DEF_FOLLOW_SYMLINKS).toBool(); + d->indexSettings.filters = s.value(CFG_FILTERS, DEF_FILTERS).toStringList(); + d->indexSettings.indexHidden = s.value(CFG_INDEX_HIDDEN, DEF_INDEX_HIDDEN).toBool(); + d->indexSettings.followSymlinks = s.value(CFG_FOLLOW_SYMLINKS, DEF_FOLLOW_SYMLINKS).toBool(); d->offlineIndex.setFuzzy(s.value(CFG_FUZZY, DEF_FUZZY).toBool()); d->indexIntervalTimer.setInterval(s.value(CFG_SCAN_INTERVAL, DEF_SCAN_INTERVAL).toInt()*60000); // Will be started in the initial index update - d->rootDirs = s.value(CFG_PATHS).toStringList(); - if (d->rootDirs.isEmpty()) + d->indexSettings.rootDirs = s.value(CFG_PATHS).toStringList(); + if (d->indexSettings.rootDirs.isEmpty()) restorePaths(); s.endGroup(); @@ -342,53 +322,8 @@ /** ***************************************************************************/ QWidget *Files::Extension::widget(QWidget *parent) { - if (d->widget.isNull()) { - d->widget = new ConfigWidget(parent); - - // Paths - d->widget->ui.listWidget_paths->addItems(d->rootDirs); - connect(this, &Extension::rootDirsChanged, d->widget->ui.listWidget_paths, &QListWidget::clear); - connect(this, &Extension::rootDirsChanged, d->widget->ui.listWidget_paths, &QListWidget::addItems); - connect(d->widget.data(), &ConfigWidget::requestAddPath, this, &Extension::addDir); - connect(d->widget.data(), &ConfigWidget::requestRemovePath, this, &Extension::removeDir); - connect(d->widget->ui.pushButton_restore, &QPushButton::clicked, this, &Extension::restorePaths); - connect(d->widget->ui.pushButton_update, &QPushButton::clicked, this, &Extension::updateIndex, Qt::QueuedConnection); - - // Checkboxes - d->widget->ui.checkBox_audio->setChecked(indexAudio()); - connect(d->widget->ui.checkBox_audio, &QCheckBox::toggled, this, &Extension::setIndexAudio); - - d->widget->ui.checkBox_video->setChecked(indexVideo()); - connect(d->widget->ui.checkBox_video, &QCheckBox::toggled, this, &Extension::setIndexVideo); - - d->widget->ui.checkBox_image->setChecked(indexImage()); - connect(d->widget->ui.checkBox_image, &QCheckBox::toggled, this, &Extension::setIndexImage); - - d->widget->ui.checkBox_docs->setChecked(indexDocs()); - connect(d->widget->ui.checkBox_docs, &QCheckBox::toggled, this, &Extension::setIndexDocs); - - d->widget->ui.checkBox_dirs->setChecked(indexDirs()); - connect(d->widget->ui.checkBox_dirs, &QCheckBox::toggled, this, &Extension::setIndexDirs); - - d->widget->ui.checkBox_hidden->setChecked(indexHidden()); - connect(d->widget->ui.checkBox_hidden, &QCheckBox::toggled, this, &Extension::setIndexHidden); - - d->widget->ui.checkBox_followSymlinks->setChecked(followSymlinks()); - connect(d->widget->ui.checkBox_followSymlinks, &QCheckBox::toggled, this, &Extension::setFollowSymlinks); - - d->widget->ui.checkBox_fuzzy->setChecked(fuzzy()); - connect(d->widget->ui.checkBox_fuzzy, &QCheckBox::toggled, this, &Extension::setFuzzy); - - d->widget->ui.spinBox_interval->setValue(scanInterval()); - connect(d->widget->ui.spinBox_interval, static_cast(&QSpinBox::valueChanged), this, &Extension::setScanInterval); - - // Status bar - ( d->futureWatcher.isRunning() ) - ? d->widget->ui.label_statusbar->setText("Indexing files ...") - : d->widget->ui.label_statusbar->setText(QString("%1 files indexed.").arg(d->index.size())); - connect(this, &Extension::statusInfo, d->widget->ui.label_statusbar, &QLabel::setText); - - } + if (d->widget.isNull()) + d->widget = new ConfigWidget(this, parent); return d->widget; } @@ -398,219 +333,127 @@ void Files::Extension::handleQuery(Core::Query * query) { - if ( query->searchTerm().startsWith('/') || query->searchTerm().startsWith("~/") ) { + if ( query->searchTerm().startsWith('/') || query->searchTerm().startsWith("~") ) { - QFileInfo fileInfo(query->searchTerm()); + QFileInfo queryFileInfo(query->searchTerm()); // Substitute tilde if ( query->searchTerm()[0] == '~' ) - fileInfo.setFile(QDir::homePath()+query->searchTerm().right(query->searchTerm().size()-1)); + queryFileInfo.setFile(QDir::homePath()+query->searchTerm().right(query->searchTerm().size()-1)); // Get all matching files - QFileInfo pathInfo(fileInfo.path()); + QFileInfo pathInfo(queryFileInfo.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())); + QDir dir(pathInfo.filePath()); + for (const QFileInfo& fileinfo : dir.entryInfoList(QDir::AllEntries|QDir::Hidden|QDir::NoDotAndDotDot, + QDir::DirsFirst|QDir::Name|QDir::IgnoreCase) ) { + if ( fileinfo.fileName().startsWith(queryFileInfo.fileName()) ) { + QMimeType mimetype = mimeDatabase.mimeTypeForFile(fileinfo.filePath()); + query->addMatch(std::make_shared(fileinfo.filePath(), mimetype), + static_cast(SHRT_MAX * static_cast(queryFileInfo.fileName().size()) / fileinfo.fileName().size())); } } } } + else + { + // Skip short terms since they pollute the output + if ( query->searchTerm().size() < 3) + return; + + if ( QString("albert scan files").startsWith(query->searchTerm()) ) { + shared_ptr standardItem = std::make_shared("org.albert.extension.files.action.index"); + standardItem->setText("albert scan files"); + standardItem->setSubtext("Update the file index"); + standardItem->setIconPath(":app_icon"); + + shared_ptr standardAction = std::make_shared(); + standardAction->setText("Update the file index"); + standardAction->setAction([this](){ this->updateIndex(); }); - // Skip short terms since they pollute the output - if ( query->searchTerm().size() < 3) - return; - - if ( QString("albert scan files").startsWith(query->searchTerm()) ) { - shared_ptr standardItem = std::make_shared("org.albert.extension.files.action.index"); - standardItem->setText("albert scan files"); - standardItem->setSubtext("Update the file index"); - standardItem->setIconPath(":app_icon"); - - shared_ptr standardAction = std::make_shared(); - standardAction->setText("Update the file index"); - standardAction->setAction([this](){ this->updateIndex(); }); - - standardItem->setActions({standardAction}); - - query->addMatch(standardItem); - } - - // Search for matches - const vector> &indexables = d->offlineIndex.search(query->searchTerm().toLower()); - - // Add results to query - vector,short>> results; - for (const shared_ptr &item : indexables) - // TODO `Search` has to determine the relevance. Set to 0 for now - results.emplace_back(std::static_pointer_cast(item), -1); - - query->addMatches(results.begin(), results.end()); -} - + standardItem->setActions({standardAction}); + query->addMatch(standardItem); + } -/** ***************************************************************************/ -void Files::Extension::addDir(const QString &dirPath) { - QFileInfo fileInfo(dirPath); + // Search for matches + const vector> &indexables = d->offlineIndex.search(query->searchTerm().toLower()); - // Get an absolute file path - QString absPath = fileInfo.absoluteFilePath(); + // Add results to query + vector,short>> results; + for (const shared_ptr &item : indexables) + // TODO `Search` has to determine the relevance. Set to 0 for now + results.emplace_back(std::static_pointer_cast(item), -1); - // Check existance - if (!fileInfo.exists()) { - QMessageBox(QMessageBox::Critical, "Error", absPath + " does not exist.").exec(); - return; - } - - // Check type - if(!fileInfo.isDir()) { - QMessageBox(QMessageBox::Critical, "Error", absPath + " is not a directory.").exec(); - return; + query->addMatches(results.begin(), results.end()); } - - // Check if there is an identical existing path - if (d->rootDirs.contains(absPath)) { - QMessageBox(QMessageBox::Critical, "Error", absPath + " has already been indexed.").exec(); - return; - } - - /* Check if this dir is a sub/superdir of an existing dir. This is fine - since user may have choosen to ignore some dirs (.albertignore). This is - more complex but also more flexible. At least inform the user */ - for (const QString &p: d->rootDirs) - if (absPath.startsWith(p + '/')) - QMessageBox(QMessageBox::Warning, "Warning", absPath + " is subdirectory of " + p).exec(); - for (const QString &p: d->rootDirs) - if (p.startsWith(absPath + '/')) - QMessageBox(QMessageBox::Warning, "Warning", p + " is subdirectory of " + absPath).exec(); - - // Add the path to root dirs - d->rootDirs << absPath; - - // Inform observers - emit rootDirsChanged(d->rootDirs); } /** ***************************************************************************/ -void Files::Extension::removeDir(const QString &dirPath) { - // Get an absolute file path - QString absPath = QFileInfo(dirPath).absoluteFilePath(); - - // Check existance - if (!d->rootDirs.contains(absPath)) - return; - - // Remove the path - d->rootDirs.removeAll(absPath); - - // Update the widget, if it is visible atm - emit rootDirsChanged(d->rootDirs); +const QStringList &Files::Extension::paths() const { + return d->indexSettings.rootDirs; } /** ***************************************************************************/ -void Files::Extension::restorePaths() { - // Add standard paths - d->rootDirs.clear(); - addDir(QStandardPaths::writableLocation(QStandardPaths::HomeLocation)); -} +void Files::Extension::setPaths(const QStringList &paths) { + d->indexSettings.rootDirs.clear(); + // Check sanity and add path + for ( const QString& path : paths ) { -/** ***************************************************************************/ -void Files::Extension::updateIndex() { - d->startIndexing(); -} - - - -/** ***************************************************************************/ -bool Files::Extension::indexAudio() { - return d->indexAudio; -} - - - -/** ***************************************************************************/ -void Files::Extension::setIndexAudio(bool b) { - QSettings(qApp->applicationName()).setValue(QString("%1/%2").arg(Core::Extension::id, CFG_INDEX_AUDIO), b); - d->indexAudio = b; -} - - - -/** ***************************************************************************/ -bool Files::Extension::indexVideo() { - return d->indexVideo; -} - - - -/** ***************************************************************************/ -void Files::Extension::setIndexVideo(bool b) { - QSettings(qApp->applicationName()).setValue(QString("%1/%2").arg(Core::Extension::id, CFG_INDEX_VIDEO), b); - d->indexVideo = b; -} - - - -/** ***************************************************************************/ -bool Files::Extension::indexImage() { - return d->indexImage; -} - - - -/** ***************************************************************************/ -void Files::Extension::setIndexImage(bool b) { - QSettings(qApp->applicationName()).setValue(QString("%1/%2").arg(Core::Extension::id, CFG_INDEX_IMAGE), b); - d->indexImage = b; -} - + QFileInfo fileInfo(path); + QString absPath = fileInfo.absoluteFilePath(); + if (d->indexSettings.rootDirs.contains(absPath)) { + qWarning() << QString("Duplicate paths: %1.").arg(path); + continue; + } -/** ***************************************************************************/ -bool Files::Extension::indexDocs() { - return d->indexDocs; -} + if (!fileInfo.exists()) { + qWarning() << QString("Path does not exist: %1.").arg(path); + continue; + } + if(!fileInfo.isDir()) { + qWarning() << QString("Path is not a directory: %1.").arg(path); + continue; + } + d->indexSettings.rootDirs << absPath; + } -/** ***************************************************************************/ -void Files::Extension::setIndexDocs(bool b) { - QSettings(qApp->applicationName()).setValue(QString("%1/%2").arg(Core::Extension::id, CFG_INDEX_DOC), b); - d->indexDocs = b; + // Store to settings + QSettings(qApp->applicationName()) + .setValue(QString("%1/%2").arg(Core::Extension::id, CFG_PATHS), d->indexSettings.rootDirs); } /** ***************************************************************************/ -bool Files::Extension::indexDirs() { - return d->indexDirs; +void Files::Extension::restorePaths() { + // Add standard path + d->indexSettings.rootDirs.clear(); + d->indexSettings.rootDirs << QStandardPaths::writableLocation(QStandardPaths::HomeLocation); } /** ***************************************************************************/ -void Files::Extension::setIndexDirs(bool b) { - QSettings(qApp->applicationName()).setValue(QString("%1/%2").arg(Core::Extension::id, CFG_INDEX_DIR), b); - d->indexDirs = b; +void Files::Extension::updateIndex() { + d->startIndexing(); } /** ***************************************************************************/ -bool Files::Extension::indexHidden() { - return d->indexHidden; +bool Files::Extension::indexHidden() const { + return d->indexSettings.indexHidden; } @@ -618,14 +461,14 @@ /** ***************************************************************************/ void Files::Extension::setIndexHidden(bool b) { QSettings(qApp->applicationName()).setValue(QString("%1/%2").arg(Core::Extension::id, CFG_INDEX_HIDDEN), b); - d->indexHidden = b; + d->indexSettings.indexHidden = b; } /** ***************************************************************************/ -bool Files::Extension::followSymlinks() { - return d->followSymlinks; +bool Files::Extension::followSymlinks() const { + return d->indexSettings.followSymlinks; } @@ -633,13 +476,13 @@ /** ***************************************************************************/ void Files::Extension::setFollowSymlinks(bool b) { QSettings(qApp->applicationName()).setValue(QString("%1/%2").arg(Core::Extension::id, CFG_FOLLOW_SYMLINKS), b); - d->followSymlinks = b; + d->indexSettings.followSymlinks = b; } /** ***************************************************************************/ -unsigned int Files::Extension::scanInterval() { +unsigned int Files::Extension::scanInterval() const { return d->indexIntervalTimer.interval()/60000; } @@ -654,7 +497,7 @@ /** ***************************************************************************/ -bool Files::Extension::fuzzy() { +bool Files::Extension::fuzzy() const { return d->offlineIndex.fuzzy(); } @@ -664,3 +507,19 @@ void Files::Extension::setFuzzy(bool b) { QSettings(qApp->applicationName()).setValue(QString("%1/%2").arg(Core::Extension::id, CFG_FUZZY), b); } + + + +/** ***************************************************************************/ +const QStringList &Files::Extension::filters() const { + return d->indexSettings.filters; +} + + + +/** ***************************************************************************/ +void Files::Extension::setFilters(const QStringList &filters) { + QSettings(qApp->applicationName()) + .setValue(QString("%1/%2").arg(Core::Extension::id, CFG_FILTERS), filters); + d->indexSettings.filters = filters; +} diff -Nru albert-0.10.3/src/plugins/files/src/main.h albert-0.11.1/src/plugins/files/src/main.h --- albert-0.10.3/src/plugins/files/src/main.h 2017-04-02 16:54:56.000000000 +0000 +++ albert-0.11.1/src/plugins/files/src/main.h 2017-04-16 11:17:45.000000000 +0000 @@ -43,6 +43,7 @@ */ QString name() const override { return "Files"; } + QStringList triggers() const override { return {"/", "~"}; } QWidget *widget(QWidget *parent = nullptr) override; void handleQuery(Core::Query * query) override; @@ -50,38 +51,25 @@ * Extension specific members */ - void addDir(const QString &dirPath); - void removeDir(const QString &dirPath); + const QStringList &paths() const; + void setPaths(const QStringList &); void restorePaths(); - // Properties - bool indexAudio(); - void setIndexAudio(bool b = true); - - bool indexVideo(); - void setIndexVideo(bool b = true); - - bool indexImage(); - void setIndexImage(bool b = true); - - bool indexDocs(); - void setIndexDocs(bool b = true); - - bool indexDirs(); - void setIndexDirs(bool b = true); - - bool indexHidden(); + bool indexHidden() const; void setIndexHidden(bool b = true); - bool followSymlinks(); + bool followSymlinks() const; void setFollowSymlinks(bool b = true); - uint scanInterval(); + uint scanInterval() const; void setScanInterval(uint minutes); - bool fuzzy(); + bool fuzzy() const; void setFuzzy(bool b = true); + const QStringList &filters() const; + void setFilters(const QStringList &); + void updateIndex(); private: diff -Nru albert-0.10.3/src/plugins/files/src/mimetypechooser.cpp albert-0.11.1/src/plugins/files/src/mimetypechooser.cpp --- albert-0.10.3/src/plugins/files/src/mimetypechooser.cpp 2017-04-02 16:54:56.000000000 +0000 +++ albert-0.11.1/src/plugins/files/src/mimetypechooser.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,39 +0,0 @@ -// 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 "mimetypechooser.h" -#include "ui_mimetypechooser.h" -#include - - -/** ***************************************************************************/ -Files::MimeTypeChooser::MimeTypeChooser(QWidget *parent) : - QDialog(parent), ui(new Ui::MimeTypeChooser) { - ui->setupUi(this); - for (QMimeType m : QMimeDatabase().allMimeTypes()) { - if (m.isValid()) { - new QListWidgetItem(m.name(),ui->listWidget_mimeTypes); - ui->listWidget_mimeTypes->sortItems(); - } - } -} - - - -/** ***************************************************************************/ -Files::MimeTypeChooser::~MimeTypeChooser() { - delete ui; -} diff -Nru albert-0.10.3/src/plugins/files/src/mimetypechooser.h albert-0.11.1/src/plugins/files/src/mimetypechooser.h --- albert-0.10.3/src/plugins/files/src/mimetypechooser.h 2017-04-02 16:54:56.000000000 +0000 +++ albert-0.11.1/src/plugins/files/src/mimetypechooser.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,36 +0,0 @@ -// 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 - -namespace Files{ -namespace Ui { -class MimeTypeChooser; -} - -class MimeTypeChooser : public QDialog -{ - Q_OBJECT - -public: - explicit MimeTypeChooser(QWidget *parent = 0); - ~MimeTypeChooser(); - -private: - Ui::MimeTypeChooser *ui; -}; -} diff -Nru albert-0.10.3/src/plugins/files/src/mimetypedialog.cpp albert-0.11.1/src/plugins/files/src/mimetypedialog.cpp --- albert-0.10.3/src/plugins/files/src/mimetypedialog.cpp 2017-04-02 16:54:56.000000000 +0000 +++ albert-0.11.1/src/plugins/files/src/mimetypedialog.cpp 2017-04-16 11:17:45.000000000 +0000 @@ -14,14 +14,74 @@ // 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 "mimetypedialog.h" #include "ui_mimetypedialog.h" /** ***************************************************************************/ -Files::MimeTypeDialog::MimeTypeDialog(QWidget *parent) : +Files::MimeTypeDialog::MimeTypeDialog(const QStringList &filters, QWidget *parent) : QDialog(parent), ui(new Ui::MimeTypeDialog) { ui->setupUi(this); + + // Populate a standard itemmodel with mime types + QStandardItemModel *standardItemModel = new QStandardItemModel(this); + for (QMimeType mimeType : QMimeDatabase().allMimeTypes()) { + QStandardItem *item = new QStandardItem; + item->setText(mimeType.name()); + item->setToolTip(mimeType.filterString()); + standardItemModel->appendRow(item); + } + standardItemModel->sort(0); + + // Add a proxy model for mimtype filtering + QSortFilterProxyModel *mimeFilterModel = new QSortFilterProxyModel(this); + mimeFilterModel->setSourceModel(standardItemModel); + ui->listView_mimeTypes->setModel(mimeFilterModel); + + // Add a stinglist model to the filter model + filtersModel = new QStringListModel(filters, this); + ui->listView_filters->setModel(filtersModel); + + // Set the filter for the proxymodel if the users typed something + connect(ui->lineEdit, &QLineEdit::textChanged, + mimeFilterModel, &QSortFilterProxyModel::setFilterFixedString); + + // On mimetype list activation add the mimetype to the filter list + connect(ui->listView_mimeTypes, &QListView::activated, [this](const QModelIndex &index){ + filtersModel->insertRow(filtersModel->rowCount()); + filtersModel->setData(filtersModel->index(filtersModel->rowCount()-1,0), index.data()); + }); + + // On ">" button click add the mimetype to the filter list + connect(ui->toolButton_copyMimetype, &QToolButton::clicked, [this](){ + QModelIndex index = ui->listView_mimeTypes->currentIndex(); + filtersModel->insertRow(filtersModel->rowCount()); + filtersModel->setData(filtersModel->index(filtersModel->rowCount()-1,0), index.data()); + }); + + // Add a new line on "+" + connect(ui->toolButton_add, &QToolButton::clicked, [this](){ + int row = filtersModel->rowCount(); + filtersModel->insertRow(row); + ui->listView_filters->setCurrentIndex(filtersModel->index(row, 0)); + ui->listView_filters->edit(filtersModel->index(row, 0)); + }); + + // Remove the selected line on "-" + connect(ui->toolButton_remove, &QToolButton::clicked, [this](){ + QModelIndex index = ui->listView_filters->currentIndex(); + if ( index.isValid() ) + filtersModel->removeRow(index.row()); + }); + + // Let the listview intercept the input of the filter line edit (for navigation and activation) + ui->lineEdit->installEventFilter(this); } @@ -30,3 +90,45 @@ Files::MimeTypeDialog::~MimeTypeDialog() { delete ui; } + + + +/** ***************************************************************************/ +QStringList Files::MimeTypeDialog::filters() const { + return filtersModel->stringList(); +} + + + +/** ***************************************************************************/ +bool Files::MimeTypeDialog::eventFilter(QObject * /*theres only the linedit*/, QEvent *event) { + + if (event->type() == QEvent::KeyPress) { + QKeyEvent *keyEvent = static_cast(event); + switch (keyEvent->key()) { + case Qt::Key_Up: + case Qt::Key_Down: + case Qt::Key_Enter: + case Qt::Key_Return: + QApplication::sendEvent(ui->listView_mimeTypes, keyEvent); + return true; + default: + return false; + } + } + return false; +} + + + +/** ***************************************************************************/ +void Files::MimeTypeDialog::keyPressEvent(QKeyEvent *evt) { + // Eat keys for desired behaviour + switch ( evt->key() ) { + case Qt::Key_Enter: + case Qt::Key_Return: + case Qt::Key_Escape: + return; + } + QDialog::keyPressEvent(evt); +} diff -Nru albert-0.10.3/src/plugins/files/src/mimetypedialog.h albert-0.11.1/src/plugins/files/src/mimetypedialog.h --- albert-0.10.3/src/plugins/files/src/mimetypedialog.h 2017-04-02 16:54:56.000000000 +0000 +++ albert-0.11.1/src/plugins/files/src/mimetypedialog.h 2017-04-16 11:17:45.000000000 +0000 @@ -16,6 +16,7 @@ #pragma once #include +#include namespace Files{ namespace Ui { @@ -27,10 +28,19 @@ Q_OBJECT public: - explicit MimeTypeDialog(QWidget *parent = 0); + + explicit MimeTypeDialog(const QStringList &filters, QWidget *parent = 0); ~MimeTypeDialog(); -private: + QStringList filters() const; + +protected: + + bool eventFilter(QObject *watched, QEvent *event) override; + void keyPressEvent(QKeyEvent *evt) override; + + QStringListModel *filtersModel; Ui::MimeTypeDialog *ui; + }; } diff -Nru albert-0.10.3/src/plugins/ssh/src/main.cpp albert-0.11.1/src/plugins/ssh/src/main.cpp --- albert-0.10.3/src/plugins/ssh/src/main.cpp 2017-04-02 16:54:56.000000000 +0000 +++ albert-0.11.1/src/plugins/ssh/src/main.cpp 2017-04-16 11:17:45.000000000 +0000 @@ -29,6 +29,7 @@ #include "standarditem.h" #include "main.h" #include "query.h" +#include "shlex.h" #include "xdgiconlookup.h" using std::shared_ptr; using std::vector; @@ -130,12 +131,6 @@ } -/** ***************************************************************************/ -QString Ssh::Extension::trigger() const { - return "ssh "; -} - - /** ***************************************************************************/ QWidget *Ssh::Extension::widget(QWidget *parent) { @@ -158,6 +153,11 @@ /** ***************************************************************************/ void Ssh::Extension::handleQuery(Core::Query * query) { + + // This extension must run only triggered + if ( !query->isTriggered() ) + return; + QStringList queryTerms = query->searchTerm().split(' ',QString::SkipEmptyParts); // Add all hosts if there are no arguments @@ -183,7 +183,11 @@ 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])); + QStringList tokens; + tokens << Util::ShellLexer::split(terminalCommand) + << "ssh" + << Util::ShellLexer::split(queryTerms[1]); + QProcess::startDetached(tokens.takeFirst(), tokens); }); item->setActions({action}); @@ -226,7 +230,11 @@ 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)); + QStringList tokens; + tokens << Util::ShellLexer::split(terminalCommand) + << "ssh" + << Util::ShellLexer::split(host); + QProcess::startDetached(tokens.takeFirst(), tokens); }); si->setActions({sa}); diff -Nru albert-0.10.3/src/plugins/ssh/src/main.h albert-0.11.1/src/plugins/ssh/src/main.h --- albert-0.10.3/src/plugins/ssh/src/main.h 2017-04-02 16:54:56.000000000 +0000 +++ albert-0.11.1/src/plugins/ssh/src/main.h 2017-04-16 11:17:45.000000000 +0000 @@ -43,8 +43,8 @@ */ QString name() const override { return "SecureShell"; } - QString trigger() const override; QWidget *widget(QWidget *parent = nullptr) override; + QStringList triggers() const override { return {"ssh "}; } void handleQuery(Core::Query * query) override; /* diff -Nru albert-0.10.3/src/plugins/templateExtension/src/main.cpp albert-0.11.1/src/plugins/templateExtension/src/main.cpp --- albert-0.10.3/src/plugins/templateExtension/src/main.cpp 2017-04-02 16:54:56.000000000 +0000 +++ albert-0.11.1/src/plugins/templateExtension/src/main.cpp 2017-04-16 11:17:45.000000000 +0000 @@ -81,7 +81,11 @@ /** ***************************************************************************/ void ProjectNamespace::Extension::handleQuery(Core::Query * query) { - // Avoid annoying warnings - Q_UNUSED(query) + + if ( query->isTriggered() ) { + + } else { + + } } diff -Nru albert-0.10.3/src/plugins/terminal/src/main.cpp albert-0.11.1/src/plugins/terminal/src/main.cpp --- albert-0.10.3/src/plugins/terminal/src/main.cpp 2017-04-02 16:54:56.000000000 +0000 +++ albert-0.11.1/src/plugins/terminal/src/main.cpp 2017-04-16 11:17:45.000000000 +0000 @@ -78,6 +78,10 @@ /** ***************************************************************************/ void Terminal::Extension::handleQuery(Core::Query * query) { + // This extension must run only triggered + if ( !query->isTriggered() ) + return; + // passwd must not be freed passwd *pwd = getpwuid(geteuid()); if (pwd == NULL){ diff -Nru albert-0.10.3/src/plugins/terminal/src/main.h albert-0.11.1/src/plugins/terminal/src/main.h --- albert-0.10.3/src/plugins/terminal/src/main.h 2017-04-02 16:54:56.000000000 +0000 +++ albert-0.11.1/src/plugins/terminal/src/main.h 2017-04-16 11:17:45.000000000 +0000 @@ -44,7 +44,7 @@ QString name() const override { return "Terminal"; } QWidget *widget(QWidget *parent = nullptr) override; - QString trigger() const override {return ">";} + QStringList triggers() const override { return {">"}; } void handleQuery(Core::Query * query) override; private: diff -Nru albert-0.10.3/src/plugins/websearch/src/enginesmodel.cpp albert-0.11.1/src/plugins/websearch/src/enginesmodel.cpp --- albert-0.10.3/src/plugins/websearch/src/enginesmodel.cpp 1970-01-01 00:00:00.000000000 +0000 +++ albert-0.11.1/src/plugins/websearch/src/enginesmodel.cpp 2017-04-16 11:17:45.000000000 +0000 @@ -0,0 +1,291 @@ +// albert - a simple application launcher for linux +// Copyright (C) 2014-2017 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 "enginesmodel.h" +#include +#include +#include +#include + +namespace { + +enum class Section{ Enabled, Name, Trigger, URL, Count }; + +std::map iconCache; + +} + + +/** ***************************************************************************/ +Websearch::EnginesModel::EnginesModel(std::vector& se, QObject *parent) + : QAbstractTableModel(parent), searchEngines_(se) { +} + + +/** ***************************************************************************/ +int Websearch::EnginesModel::rowCount(const QModelIndex &) const { + return static_cast(searchEngines_.size()); +} + + + +/** ***************************************************************************/ +int Websearch::EnginesModel::columnCount(const QModelIndex &) const { + return static_cast(Section::Count); +} + + + +/** ***************************************************************************/ +QVariant Websearch::EnginesModel::headerData(int section, Qt::Orientation orientation, int role) const { + // No sanity check necessary since + if ( section<0 || static_cast(Section::Count)<=section ) + return QVariant(); + + + if (orientation == Qt::Horizontal){ + switch (static_cast
(section)) { + case Section::Enabled:{ + switch (role) { + case Qt::ToolTipRole: return "Enables the searchengine as fallback."; + default: return QVariant(); + } + } + case Section::Name:{ + switch (role) { + case Qt::DisplayRole: return "Name"; + case Qt::ToolTipRole: return "The name of the searchengine."; + default: return QVariant(); + } + + } + case Section::Trigger:{ + switch (role) { + case Qt::DisplayRole: return "Trigger"; + case Qt::ToolTipRole: return "The term that triggers this searchengine."; + default: return QVariant(); + } + + } + case Section::URL:{ + switch (role) { + case Qt::DisplayRole: return "URL"; + case Qt::ToolTipRole: return "The URL of this searchengine. %s will be replaced by your searchterm."; + default: return QVariant(); + } + + } + case Section::Count: + return QVariant(); + } + } + return QVariant(); +} + + + +/** ***************************************************************************/ +QVariant Websearch::EnginesModel::data(const QModelIndex &index, int role) const { + if (!index.isValid() + || index.row() >= static_cast(searchEngines_.size()) + || index.column() >= static_cast(static_cast(Section::Count))) + return QVariant(); + + switch (role) { + case Qt::DisplayRole: { + switch (static_cast
(index.column())) { + case Section::Name: return searchEngines_[index.row()].name; + case Section::Trigger: return searchEngines_[index.row()].trigger; + case Section::URL: return searchEngines_[index.row()].url; + default: return QVariant(); + } + } + case Qt::EditRole: { + switch (static_cast
(index.column())) { + case Section::Name: return searchEngines_[index.row()].name; + case Section::Trigger: return searchEngines_[index.row()].trigger; + case Section::URL: return searchEngines_[index.row()].url; + default: return QVariant(); + } + } + case Qt::DecorationRole: { + switch (static_cast
(index.column())) { + case Section::Name:{ + // Resizing request thounsands of repaints. Creating an icon for + // ever paint event is to expensive. Therefor maintain an icon cache + QString &iconPath = searchEngines_[index.row()].iconPath; + decltype(iconCache)::iterator it = iconCache.find(iconPath); + if ( it != iconCache.end() ) + return it->second; + return iconCache.emplace(iconPath, QIcon(iconPath)).second; + } + default: return QVariant(); + } + } + case Qt::ToolTipRole: { + switch (static_cast
(index.column())) { + case Section::Enabled: return "Check to use as fallback"; + default: return "Double click to edit"; + } + } + case Qt::CheckStateRole: { + switch (static_cast
(index.column())) { + case Section::Enabled: return (searchEngines_[index.row()].enabled)?Qt::Checked:Qt::Unchecked; + default: return QVariant(); + } + } + default: + return QVariant(); + } +} + + + +/** ***************************************************************************/ +bool Websearch::EnginesModel::setData(const QModelIndex &index, const QVariant &value, int role) { + if (!index.isValid() + || index.row() >= static_cast(searchEngines_.size()) + || index.column() >= static_cast(static_cast(Section::Count))) + return false; + + switch (role) { + case Qt::EditRole: { + if ( !value.canConvert(QMetaType::QString) ) + return false; + QString s = value.toString(); + switch (static_cast
(index.column())) { + case Section::Enabled: + return false; + case Section::Name: + searchEngines_[index.row()].name = s; + dataChanged(index, index, QVector({Qt::DisplayRole})); + return true; + case Section::Trigger: + searchEngines_[index.row()].trigger = s; + dataChanged(index, index, QVector({Qt::DisplayRole})); + return true; + case Section::URL: + searchEngines_[index.row()].url = s; + dataChanged(index, index, QVector({Qt::DisplayRole})); + return true; + default: + return false; + } + } + case Qt::CheckStateRole: { + switch (static_cast
(index.column())) { + case Section::Enabled: + searchEngines_[index.row()].enabled = value.toBool(); + dataChanged(index, index, QVector({Qt::CheckStateRole})); + return true; + default: + return false; + } + } + case Qt::DecorationRole: { + QFileInfo fileInfo(value.toString()); + QString newFilePath; + uint i = 0; + do { + // Build the new path in cache dir + newFilePath = QDir(QStandardPaths::writableLocation(QStandardPaths::CacheLocation)) + .filePath(QString("%1-%2.%3") + .arg(searchEngines_[index.row()].name) + .arg(i++) + .arg(fileInfo.suffix())); + // Copy the file into cache dir + } while (!QFile::copy(fileInfo.filePath(), newFilePath)); + // Set the copied file as icon + searchEngines_[index.row()].iconPath = newFilePath; + dataChanged(index, index, QVector({Qt::DecorationRole})); + iconCache.clear(); + return true; + } + default: + return false; + } + return false; +} + + + +/** ***************************************************************************/ +Qt::ItemFlags Websearch::EnginesModel::flags(const QModelIndex &index) const { + if (!index.isValid()) + return Qt::NoItemFlags; + + switch (static_cast
(index.column())) { + case Section::Enabled: + return Qt::ItemIsSelectable|Qt::ItemIsEnabled|Qt::ItemIsUserCheckable; + default: + return Qt::ItemIsSelectable|Qt::ItemIsEnabled|Qt::ItemIsEditable; + } +} + + + +/** ***************************************************************************/ +bool Websearch::EnginesModel::insertRows(int position, int rows, const QModelIndex &) { + if (position<0 || rows<1 || static_cast(searchEngines_.size())", + "", + ":default", + ""})); + } + endInsertRows(); + return true; +} + + + +/** ***************************************************************************/ +bool Websearch::EnginesModel::removeRows(int position, int rows, const QModelIndex &) { + if (position<0 || rows<1 || static_cast(searchEngines_.size())(searchEngines_.size())(searchEngines_.size()) tmp; + beginMoveRows(src, srcRow, srcRow+cnt-1, dst, dstRow); + tmp.insert(tmp.end(), make_move_iterator(searchEngines_.begin()+srcRow), make_move_iterator(searchEngines_.begin() + srcRow+cnt)); + searchEngines_.erase(searchEngines_.begin()+srcRow, searchEngines_.begin() + srcRow+cnt); + const size_t finalDst = dstRow > srcRow ? dstRow - cnt : dstRow; + searchEngines_.insert(searchEngines_.begin()+finalDst , make_move_iterator(tmp.begin()), make_move_iterator(tmp.end())); + endMoveRows(); + return true; +} + diff -Nru albert-0.10.3/src/plugins/websearch/src/enginesmodel.h albert-0.11.1/src/plugins/websearch/src/enginesmodel.h --- albert-0.10.3/src/plugins/websearch/src/enginesmodel.h 1970-01-01 00:00:00.000000000 +0000 +++ albert-0.11.1/src/plugins/websearch/src/enginesmodel.h 2017-04-16 11:17:45.000000000 +0000 @@ -0,0 +1,54 @@ +// albert - a simple application launcher for linux +// Copyright (C) 2014-2017 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 + +namespace Websearch { + +struct SearchEngine { + bool enabled; + QString name; + QString trigger; + QString iconPath; + QString url; +}; + +class EnginesModel final : public QAbstractTableModel +{ + Q_OBJECT + +public: + + EnginesModel(std::vector&, QObject *parent = Q_NULLPTR); + + int rowCount(const QModelIndex & parent = QModelIndex()) const override; + int columnCount(const QModelIndex & parent = QModelIndex()) const override; + QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; + QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const override; + bool setData(const QModelIndex & index, const QVariant & value, int role = Qt::EditRole) override; + Qt::ItemFlags flags(const QModelIndex & index) const override; + bool insertRows (int position, int rows, const QModelIndex & parent = QModelIndex()) override; + bool removeRows (int position, int rows, const QModelIndex & parent = QModelIndex()) override; + bool moveRows(const QModelIndex &sourceRow, int srcRow, int cnt, const QModelIndex & dst, int destinationChild) override; + +private: + + std::vector &searchEngines_; + +}; + +} diff -Nru albert-0.10.3/src/plugins/websearch/src/main.cpp albert-0.11.1/src/plugins/websearch/src/main.cpp --- albert-0.10.3/src/plugins/websearch/src/main.cpp 2017-04-02 16:54:56.000000000 +0000 +++ albert-0.11.1/src/plugins/websearch/src/main.cpp 2017-04-16 11:17:45.000000000 +0000 @@ -14,26 +14,29 @@ // 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 #include #include +#include #include #include -#include "main.h" +#include #include "configwidget.h" +#include "enginesmodel.h" #include "item.h" -#include "standarditem.h" +#include "main.h" #include "standardaction.h" +#include "standarditem.h" #include "query.h" +#include "xdgiconlookup.h" using std::shared_ptr; using std::vector; using namespace Core; @@ -41,19 +44,209 @@ namespace { -enum class Section{ Enabled, Name, Trigger, URL, Count }; - -std::map iconCache; - -struct SearchEngine { - bool enabled; - QString name; - QString trigger; - QString iconPath; - QString url; +// http://data.iana.org/TLD/tlds-alpha-by-domain.txt +// Version 2017032500, Last Updated Sat Mar 25 07:07:02 2017 UTC +std::array validTlds = { {"AAA", "AARP", "ABARTH", "ABB", +"ABBOTT", "ABBVIE", "ABC", "ABLE", "ABOGADO", "ABUDHABI", "AC", "ACADEMY", +"ACCENTURE", "ACCOUNTANT", "ACCOUNTANTS", "ACO", "ACTIVE", "ACTOR", "AD", +"ADAC", "ADS", "ADULT", "AE", "AEG", "AERO", "AETNA", "AF", "AFAMILYCOMPANY", +"AFL", "AFRICA", "AG", "AGAKHAN", "AGENCY", "AI", "AIG", "AIGO", "AIRBUS", +"AIRFORCE", "AIRTEL", "AKDN", "AL", "ALFAROMEO", "ALIBABA", "ALIPAY", +"ALLFINANZ", "ALLSTATE", "ALLY", "ALSACE", "ALSTOM", "AM", "AMERICANEXPRESS", +"AMERICANFAMILY", "AMEX", "AMFAM", "AMICA", "AMSTERDAM", "ANALYTICS", +"ANDROID", "ANQUAN", "ANZ", "AO", "AOL", "APARTMENTS", "APP", "APPLE", "AQ", +"AQUARELLE", "AR", "ARAMCO", "ARCHI", "ARMY", "ARPA", "ART", "ARTE", "AS", +"ASDA", "ASIA", "ASSOCIATES", "AT", "ATHLETA", "ATTORNEY", "AU", "AUCTION", +"AUDI", "AUDIBLE", "AUDIO", "AUSPOST", "AUTHOR", "AUTO", "AUTOS", "AVIANCA", +"AW", "AWS", "AX", "AXA", "AZ", "AZURE", "BA", "BABY", "BAIDU", "BANAMEX", +"BANANAREPUBLIC", "BAND", "BANK", "BAR", "BARCELONA", "BARCLAYCARD", +"BARCLAYS", "BAREFOOT", "BARGAINS", "BASEBALL", "BASKETBALL", "BAUHAUS", +"BAYERN", "BB", "BBC", "BBT", "BBVA", "BCG", "BCN", "BD", "BE", "BEATS", +"BEAUTY", "BEER", "BENTLEY", "BERLIN", "BEST", "BESTBUY", "BET", "BF", "BG", +"BH", "BHARTI", "BI", "BIBLE", "BID", "BIKE", "BING", "BINGO", "BIO", "BIZ", +"BJ", "BLACK", "BLACKFRIDAY", "BLANCO", "BLOCKBUSTER", "BLOG", "BLOOMBERG", +"BLUE", "BM", "BMS", "BMW", "BN", "BNL", "BNPPARIBAS", "BO", "BOATS", +"BOEHRINGER", "BOFA", "BOM", "BOND", "BOO", "BOOK", "BOOKING", "BOOTS", +"BOSCH", "BOSTIK", "BOSTON", "BOT", "BOUTIQUE", "BOX", "BR", "BRADESCO", +"BRIDGESTONE", "BROADWAY", "BROKER", "BROTHER", "BRUSSELS", "BS", "BT", +"BUDAPEST", "BUGATTI", "BUILD", "BUILDERS", "BUSINESS", "BUY", "BUZZ", "BV", +"BW", "BY", "BZ", "BZH", "CA", "CAB", "CAFE", "CAL", "CALL", "CALVINKLEIN", +"CAM", "CAMERA", "CAMP", "CANCERRESEARCH", "CANON", "CAPETOWN", "CAPITAL", +"CAPITALONE", "CAR", "CARAVAN", "CARDS", "CARE", "CAREER", "CAREERS", "CARS", +"CARTIER", "CASA", "CASE", "CASEIH", "CASH", "CASINO", "CAT", "CATERING", +"CATHOLIC", "CBA", "CBN", "CBRE", "CBS", "CC", "CD", "CEB", "CENTER", "CEO", +"CERN", "CF", "CFA", "CFD", "CG", "CH", "CHANEL", "CHANNEL", "CHASE", "CHAT", +"CHEAP", "CHINTAI", "CHLOE", "CHRISTMAS", "CHROME", "CHRYSLER", "CHURCH", "CI", +"CIPRIANI", "CIRCLE", "CISCO", "CITADEL", "CITI", "CITIC", "CITY", "CITYEATS", +"CK", "CL", "CLAIMS", "CLEANING", "CLICK", "CLINIC", "CLINIQUE", "CLOTHING", +"CLOUD", "CLUB", "CLUBMED", "CM", "CN", "CO", "COACH", "CODES", "COFFEE", +"COLLEGE", "COLOGNE", "COM", "COMCAST", "COMMBANK", "COMMUNITY", "COMPANY", +"COMPARE", "COMPUTER", "COMSEC", "CONDOS", "CONSTRUCTION", "CONSULTING", +"CONTACT", "CONTRACTORS", "COOKING", "COOKINGCHANNEL", "COOL", "COOP", +"CORSICA", "COUNTRY", "COUPON", "COUPONS", "COURSES", "CR", "CREDIT", +"CREDITCARD", "CREDITUNION", "CRICKET", "CROWN", "CRS", "CRUISE", "CRUISES", +"CSC", "CU", "CUISINELLA", "CV", "CW", "CX", "CY", "CYMRU", "CYOU", "CZ", +"DABUR", "DAD", "DANCE", "DATA", "DATE", "DATING", "DATSUN", "DAY", "DCLK", +"DDS", "DE", "DEAL", "DEALER", "DEALS", "DEGREE", "DELIVERY", "DELL", +"DELOITTE", "DELTA", "DEMOCRAT", "DENTAL", "DENTIST", "DESI", "DESIGN", "DEV", +"DHL", "DIAMONDS", "DIET", "DIGITAL", "DIRECT", "DIRECTORY", "DISCOUNT", +"DISCOVER", "DISH", "DIY", "DJ", "DK", "DM", "DNP", "DO", "DOCS", "DOCTOR", +"DODGE", "DOG", "DOHA", "DOMAINS", "DOT", "DOWNLOAD", "DRIVE", "DTV", "DUBAI", +"DUCK", "DUNLOP", "DUNS", "DUPONT", "DURBAN", "DVAG", "DVR", "DZ", "EARTH", +"EAT", "EC", "ECO", "EDEKA", "EDU", "EDUCATION", "EE", "EG", "EMAIL", "EMERCK", +"ENERGY", "ENGINEER", "ENGINEERING", "ENTERPRISES", "EPOST", "EPSON", +"EQUIPMENT", "ER", "ERICSSON", "ERNI", "ES", "ESQ", "ESTATE", "ESURANCE", "ET", +"EU", "EUROVISION", "EUS", "EVENTS", "EVERBANK", "EXCHANGE", "EXPERT", +"EXPOSED", "EXPRESS", "EXTRASPACE", "FAGE", "FAIL", "FAIRWINDS", "FAITH", +"FAMILY", "FAN", "FANS", "FARM", "FARMERS", "FASHION", "FAST", "FEDEX", +"FEEDBACK", "FERRARI", "FERRERO", "FI", "FIAT", "FIDELITY", "FIDO", "FILM", +"FINAL", "FINANCE", "FINANCIAL", "FIRE", "FIRESTONE", "FIRMDALE", "FISH", +"FISHING", "FIT", "FITNESS", "FJ", "FK", "FLICKR", "FLIGHTS", "FLIR", +"FLORIST", "FLOWERS", "FLY", "FM", "FO", "FOO", "FOOD", "FOODNETWORK", +"FOOTBALL", "FORD", "FOREX", "FORSALE", "FORUM", "FOUNDATION", "FOX", "FR", +"FREE", "FRESENIUS", "FRL", "FROGANS", "FRONTDOOR", "FRONTIER", "FTR", +"FUJITSU", "FUJIXEROX", "FUN", "FUND", "FURNITURE", "FUTBOL", "FYI", "GA", +"GAL", "GALLERY", "GALLO", "GALLUP", "GAME", "GAMES", "GAP", "GARDEN", "GB", +"GBIZ", "GD", "GDN", "GE", "GEA", "GENT", "GENTING", "GEORGE", "GF", "GG", +"GGEE", "GH", "GI", "GIFT", "GIFTS", "GIVES", "GIVING", "GL", "GLADE", "GLASS", +"GLE", "GLOBAL", "GLOBO", "GM", "GMAIL", "GMBH", "GMO", "GMX", "GN", "GODADDY", +"GOLD", "GOLDPOINT", "GOLF", "GOO", "GOODHANDS", "GOODYEAR", "GOOG", "GOOGLE", +"GOP", "GOT", "GOV", "GP", "GQ", "GR", "GRAINGER", "GRAPHICS", "GRATIS", +"GREEN", "GRIPE", "GROUP", "GS", "GT", "GU", "GUARDIAN", "GUCCI", "GUGE", +"GUIDE", "GUITARS", "GURU", "GW", "GY", "HAIR", "HAMBURG", "HANGOUT", "HAUS", +"HBO", "HDFC", "HDFCBANK", "HEALTH", "HEALTHCARE", "HELP", "HELSINKI", "HERE", +"HERMES", "HGTV", "HIPHOP", "HISAMITSU", "HITACHI", "HIV", "HK", "HKT", "HM", +"HN", "HOCKEY", "HOLDINGS", "HOLIDAY", "HOMEDEPOT", "HOMEGOODS", "HOMES", +"HOMESENSE", "HONDA", "HONEYWELL", "HORSE", "HOSPITAL", "HOST", "HOSTING", +"HOT", "HOTELES", "HOTMAIL", "HOUSE", "HOW", "HR", "HSBC", "HT", "HTC", "HU", +"HUGHES", "HYATT", "HYUNDAI", "IBM", "ICBC", "ICE", "ICU", "ID", "IE", "IEEE", +"IFM", "IKANO", "IL", "IM", "IMAMAT", "IMDB", "IMMO", "IMMOBILIEN", "IN", +"INDUSTRIES", "INFINITI", "INFO", "ING", "INK", "INSTITUTE", "INSURANCE", +"INSURE", "INT", "INTEL", "INTERNATIONAL", "INTUIT", "INVESTMENTS", "IO", +"IPIRANGA", "IQ", "IR", "IRISH", "IS", "ISELECT", "ISMAILI", "IST", "ISTANBUL", +"IT", "ITAU", "ITV", "IVECO", "IWC", "JAGUAR", "JAVA", "JCB", "JCP", "JE", +"JEEP", "JETZT", "JEWELRY", "JIO", "JLC", "JLL", "JM", "JMP", "JNJ", "JO", +"JOBS", "JOBURG", "JOT", "JOY", "JP", "JPMORGAN", "JPRS", "JUEGOS", "JUNIPER", +"KAUFEN", "KDDI", "KE", "KERRYHOTELS", "KERRYLOGISTICS", "KERRYPROPERTIES", +"KFH", "KG", "KH", "KI", "KIA", "KIM", "KINDER", "KINDLE", "KITCHEN", "KIWI", +"KM", "KN", "KOELN", "KOMATSU", "KOSHER", "KP", "KPMG", "KPN", "KR", "KRD", +"KRED", "KUOKGROUP", "KW", "KY", "KYOTO", "KZ", "LA", "LACAIXA", "LADBROKES", +"LAMBORGHINI", "LAMER", "LANCASTER", "LANCIA", "LANCOME", "LAND", "LANDROVER", +"LANXESS", "LASALLE", "LAT", "LATINO", "LATROBE", "LAW", "LAWYER", "LB", "LC", +"LDS", "LEASE", "LECLERC", "LEFRAK", "LEGAL", "LEGO", "LEXUS", "LGBT", "LI", +"LIAISON", "LIDL", "LIFE", "LIFEINSURANCE", "LIFESTYLE", "LIGHTING", "LIKE", +"LILLY", "LIMITED", "LIMO", "LINCOLN", "LINDE", "LINK", "LIPSY", "LIVE", +"LIVING", "LIXIL", "LK", "LOAN", "LOANS", "LOCKER", "LOCUS", "LOFT", "LOL", +"LONDON", "LOTTE", "LOTTO", "LOVE", "LPL", "LPLFINANCIAL", "LR", "LS", "LT", +"LTD", "LTDA", "LU", "LUNDBECK", "LUPIN", "LUXE", "LUXURY", "LV", "LY", "MA", +"MACYS", "MADRID", "MAIF", "MAISON", "MAKEUP", "MAN", "MANAGEMENT", "MANGO", +"MARKET", "MARKETING", "MARKETS", "MARRIOTT", "MARSHALLS", "MASERATI", +"MATTEL", "MBA", "MC", "MCD", "MCDONALDS", "MCKINSEY", "MD", "ME", "MED", +"MEDIA", "MEET", "MELBOURNE", "MEME", "MEMORIAL", "MEN", "MENU", "MEO", +"METLIFE", "MG", "MH", "MIAMI", "MICROSOFT", "MIL", "MINI", "MINT", "MIT", +"MITSUBISHI", "MK", "ML", "MLB", "MLS", "MM", "MMA", "MN", "MO", "MOBI", +"MOBILE", "MOBILY", "MODA", "MOE", "MOI", "MOM", "MONASH", "MONEY", "MONSTER", +"MONTBLANC", "MOPAR", "MORMON", "MORTGAGE", "MOSCOW", "MOTO", "MOTORCYCLES", +"MOV", "MOVIE", "MOVISTAR", "MP", "MQ", "MR", "MS", "MSD", "MT", "MTN", "MTPC", +"MTR", "MU", "MUSEUM", "MUTUAL", "MV", "MW", "MX", "MY", "MZ", "NA", "NAB", +"NADEX", "NAGOYA", "NAME", "NATIONWIDE", "NATURA", "NAVY", "NBA", "NC", "NE", +"NEC", "NET", "NETBANK", "NETFLIX", "NETWORK", "NEUSTAR", "NEW", "NEWHOLLAND", +"NEWS", "NEXT", "NEXTDIRECT", "NEXUS", "NF", "NFL", "NG", "NGO", "NHK", "NI", +"NICO", "NIKE", "NIKON", "NINJA", "NISSAN", "NISSAY", "NL", "NO", "NOKIA", +"NORTHWESTERNMUTUAL", "NORTON", "NOW", "NOWRUZ", "NOWTV", "NP", "NR", "NRA", +"NRW", "NTT", "NU", "NYC", "NZ", "OBI", "OBSERVER", "OFF", "OFFICE", "OKINAWA", +"OLAYAN", "OLAYANGROUP", "OLDNAVY", "OLLO", "OM", "OMEGA", "ONE", "ONG", "ONL", +"ONLINE", "ONYOURSIDE", "OOO", "OPEN", "ORACLE", "ORANGE", "ORG", "ORGANIC", +"ORIENTEXPRESS", "ORIGINS", "OSAKA", "OTSUKA", "OTT", "OVH", "PA", "PAGE", +"PAMPEREDCHEF", "PANASONIC", "PANERAI", "PARIS", "PARS", "PARTNERS", "PARTS", +"PARTY", "PASSAGENS", "PAY", "PCCW", "PE", "PET", "PF", "PFIZER", "PG", "PH", +"PHARMACY", "PHILIPS", "PHONE", "PHOTO", "PHOTOGRAPHY", "PHOTOS", "PHYSIO", +"PIAGET", "PICS", "PICTET", "PICTURES", "PID", "PIN", "PING", "PINK", +"PIONEER", "PIZZA", "PK", "PL", "PLACE", "PLAY", "PLAYSTATION", "PLUMBING", +"PLUS", "PM", "PN", "PNC", "POHL", "POKER", "POLITIE", "PORN", "POST", "PR", +"PRAMERICA", "PRAXI", "PRESS", "PRIME", "PRO", "PROD", "PRODUCTIONS", "PROF", +"PROGRESSIVE", "PROMO", "PROPERTIES", "PROPERTY", "PROTECTION", "PRU", +"PRUDENTIAL", "PS", "PT", "PUB", "PW", "PWC", "PY", "QA", "QPON", "QUEBEC", +"QUEST", "QVC", "RACING", "RADIO", "RAID", "RE", "READ", "REALESTATE", +"REALTOR", "REALTY", "RECIPES", "RED", "REDSTONE", "REDUMBRELLA", "REHAB", +"REISE", "REISEN", "REIT", "RELIANCE", "REN", "RENT", "RENTALS", "REPAIR", +"REPORT", "REPUBLICAN", "REST", "RESTAURANT", "REVIEW", "REVIEWS", "REXROTH", +"RICH", "RICHARDLI", "RICOH", "RIGHTATHOME", "RIL", "RIO", "RIP", "RMIT", "RO", +"ROCHER", "ROCKS", "RODEO", "ROGERS", "ROOM", "RS", "RSVP", "RU", "RUHR", +"RUN", "RW", "RWE", "RYUKYU", "SA", "SAARLAND", "SAFE", "SAFETY", "SAKURA", +"SALE", "SALON", "SAMSCLUB", "SAMSUNG", "SANDVIK", "SANDVIKCOROMANT", "SANOFI", +"SAP", "SAPO", "SARL", "SAS", "SAVE", "SAXO", "SB", "SBI", "SBS", "SC", "SCA", +"SCB", "SCHAEFFLER", "SCHMIDT", "SCHOLARSHIPS", "SCHOOL", "SCHULE", "SCHWARZ", +"SCIENCE", "SCJOHNSON", "SCOR", "SCOT", "SD", "SE", "SEAT", "SECURE", +"SECURITY", "SEEK", "SELECT", "SENER", "SERVICES", "SES", "SEVEN", "SEW", +"SEX", "SEXY", "SFR", "SG", "SH", "SHANGRILA", "SHARP", "SHAW", "SHELL", +"SHIA", "SHIKSHA", "SHOES", "SHOP", "SHOPPING", "SHOUJI", "SHOW", "SHOWTIME", +"SHRIRAM", "SI", "SILK", "SINA", "SINGLES", "SITE", "SJ", "SK", "SKI", "SKIN", +"SKY", "SKYPE", "SL", "SLING", "SM", "SMART", "SMILE", "SN", "SNCF", "SO", +"SOCCER", "SOCIAL", "SOFTBANK", "SOFTWARE", "SOHU", "SOLAR", "SOLUTIONS", +"SONG", "SONY", "SOY", "SPACE", "SPIEGEL", "SPOT", "SPREADBETTING", "SR", +"SRL", "SRT", "ST", "STADA", "STAPLES", "STAR", "STARHUB", "STATEBANK", +"STATEFARM", "STATOIL", "STC", "STCGROUP", "STOCKHOLM", "STORAGE", "STORE", +"STREAM", "STUDIO", "STUDY", "STYLE", "SU", "SUCKS", "SUPPLIES", "SUPPLY", +"SUPPORT", "SURF", "SURGERY", "SUZUKI", "SV", "SWATCH", "SWIFTCOVER", "SWISS", +"SX", "SY", "SYDNEY", "SYMANTEC", "SYSTEMS", "SZ", "TAB", "TAIPEI", "TALK", +"TAOBAO", "TARGET", "TATAMOTORS", "TATAR", "TATTOO", "TAX", "TAXI", "TC", +"TCI", "TD", "TDK", "TEAM", "TECH", "TECHNOLOGY", "TEL", "TELECITY", +"TELEFONICA", "TEMASEK", "TENNIS", "TEVA", "TF", "TG", "TH", "THD", "THEATER", +"THEATRE", "TIAA", "TICKETS", "TIENDA", "TIFFANY", "TIPS", "TIRES", "TIROL", +"TJ", "TJMAXX", "TJX", "TK", "TKMAXX", "TL", "TM", "TMALL", "TN", "TO", +"TODAY", "TOKYO", "TOOLS", "TOP", "TORAY", "TOSHIBA", "TOTAL", "TOURS", "TOWN", +"TOYOTA", "TOYS", "TR", "TRADE", "TRADING", "TRAINING", "TRAVEL", +"TRAVELCHANNEL", "TRAVELERS", "TRAVELERSINSURANCE", "TRUST", "TRV", "TT", +"TUBE", "TUI", "TUNES", "TUSHU", "TV", "TVS", "TW", "TZ", "UA", "UBANK", "UBS", +"UCONNECT", "UG", "UK", "UNICOM", "UNIVERSITY", "UNO", "UOL", "UPS", "US", +"UY", "UZ", "VA", "VACATIONS", "VANA", "VANGUARD", "VC", "VE", "VEGAS", +"VENTURES", "VERISIGN", "VERSICHERUNG", "VET", "VG", "VI", "VIAJES", "VIDEO", +"VIG", "VIKING", "VILLAS", "VIN", "VIP", "VIRGIN", "VISA", "VISION", "VISTA", +"VISTAPRINT", "VIVA", "VIVO", "VLAANDEREN", "VN", "VODKA", "VOLKSWAGEN", +"VOLVO", "VOTE", "VOTING", "VOTO", "VOYAGE", "VU", "VUELOS", "WALES", +"WALMART", "WALTER", "WANG", "WANGGOU", "WARMAN", "WATCH", "WATCHES", +"WEATHER", "WEATHERCHANNEL", "WEBCAM", "WEBER", "WEBSITE", "WED", "WEDDING", +"WEIBO", "WEIR", "WF", "WHOSWHO", "WIEN", "WIKI", "WILLIAMHILL", "WIN", +"WINDOWS", "WINE", "WINNERS", "WME", "WOLTERSKLUWER", "WOODSIDE", "WORK", +"WORKS", "WORLD", "WOW", "WS", "WTC", "WTF", "XBOX", "XEROX", "XFINITY", +"XIHUAN", "XIN", "XN--11B4C3D", "XN--1CK2E1B", "XN--1QQW23A", "XN--30RR7Y", +"XN--3BST00M", "XN--3DS443G", "XN--3E0B707E", "XN--3OQ18VL8PN36A", +"XN--3PXU8K", "XN--42C2D9A", "XN--45BRJ9C", "XN--45Q11C", "XN--4GBRIM", +"XN--54B7FTA0CC", "XN--55QW42G", "XN--55QX5D", "XN--5SU34J936BGSG", +"XN--5TZM5G", "XN--6FRZ82G", "XN--6QQ986B3XL", "XN--80ADXHKS", "XN--80AO21A", +"XN--80AQECDR1A", "XN--80ASEHDB", "XN--80ASWG", "XN--8Y0A063A", "XN--90A3AC", +"XN--90AE", "XN--90AIS", "XN--9DBQ2A", "XN--9ET52U", "XN--9KRT00A", +"XN--B4W605FERD", "XN--BCK1B9A5DRE4C", "XN--C1AVG", "XN--C2BR7G", +"XN--CCK2B3B", "XN--CG4BKI", "XN--CLCHC0EA0B2G2A9GCD", "XN--CZR694B", +"XN--CZRS0T", "XN--CZRU2D", "XN--D1ACJ3B", "XN--D1ALF", "XN--E1A4C", +"XN--ECKVDTC9D", "XN--EFVY88H", "XN--ESTV75G", "XN--FCT429K", "XN--FHBEI", +"XN--FIQ228C5HS", "XN--FIQ64B", "XN--FIQS8S", "XN--FIQZ9S", "XN--FJQ720A", +"XN--FLW351E", "XN--FPCRJ9C3D", "XN--FZC2C9E2C", "XN--FZYS8D69UVGM", +"XN--G2XX48C", "XN--GCKR3F0F", "XN--GECRJ9C", "XN--GK3AT1E", "XN--H2BRJ9C", +"XN--HXT814E", "XN--I1B6B1A6A2E", "XN--IMR513N", "XN--IO0A7I", "XN--J1AEF", +"XN--J1AMH", "XN--J6W193G", "XN--JLQ61U9W7B", "XN--JVR189M", "XN--KCRX77D1X4A", +"XN--KPRW13D", "XN--KPRY57D", "XN--KPU716F", "XN--KPUT3I", "XN--L1ACC", +"XN--LGBBAT1AD8J", "XN--MGB9AWBF", "XN--MGBA3A3EJT", "XN--MGBA3A4F16A", +"XN--MGBA7C0BBN0A", "XN--MGBAAM7A8H", "XN--MGBAB2BD", "XN--MGBAI9AZGQP6J", +"XN--MGBAYH7GPA", "XN--MGBB9FBPOB", "XN--MGBBH1A71E", "XN--MGBC0A9AZCG", +"XN--MGBCA7DZDO", "XN--MGBERP4A5D4AR", "XN--MGBI4ECEXP", "XN--MGBPL2FH", +"XN--MGBT3DHD", "XN--MGBTX2B", "XN--MGBX4CD0AB", "XN--MIX891F", "XN--MK1BU44C", +"XN--MXTQ1M", "XN--NGBC5AZD", "XN--NGBE9E0A", "XN--NODE", "XN--NQV7F", +"XN--NQV7FS00EMA", "XN--NYQY26A", "XN--O3CW4H", "XN--OGBPF8FL", "XN--P1ACF", +"XN--P1AI", "XN--PBT977C", "XN--PGBS0DH", "XN--PSSY2U", "XN--Q9JYB4C", +"XN--QCKA1PMC", "XN--QXAM", "XN--RHQV96G", "XN--ROVU88B", "XN--S9BRJ9C", +"XN--SES554G", "XN--T60B56A", "XN--TCKWE", "XN--TIQ49XQYJ", "XN--UNUP4Y", +"XN--VERMGENSBERATER-CTB", "XN--VERMGENSBERATUNG-PWB", "XN--VHQUV", +"XN--VUQ861B", "XN--W4R85EL8FHU5DNRA", "XN--W4RS40L", "XN--WGBH1C", +"XN--WGBL6A", "XN--XHQ521B", "XN--XKC2AL3HYE2A", "XN--XKC2DL3A5EE0H", +"XN--Y9A3AQ", "XN--YFRO4I67O", "XN--YGBI2AMMX", "XN--ZFR164B", "XPERIA", "XXX", +"XYZ", "YACHTS", "YAHOO", "YAMAXUN", "YANDEX", "YE", "YODOBASHI", "YOGA", +"YOKOHAMA", "YOU", "YOUTUBE", "YT", "YUN", "ZA", "ZAPPOS", "ZARA", "ZERO", +"ZIP", "ZIPPO", "ZM", "ZONE", "ZUERICH", "ZW"} }; -std::vector defaultSearchEngines = { +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"}, @@ -63,7 +256,7 @@ {true, "Wolfram Alpha", "=", ":wolfram", "https://www.wolframalpha.com/input/?i=%s"} }; -shared_ptr buildWebsearchItem(const SearchEngine &se, const QString &searchterm) { +shared_ptr buildWebsearchItem(const Websearch::SearchEngine &se, const QString &searchterm) { QString urlString = QString(se.url).replace("%s", QUrl::toPercentEncoding(searchterm)); QUrl url = QUrl(urlString); @@ -90,102 +283,24 @@ /** ***************************************************************************/ /** ***************************************************************************/ /** ***************************************************************************/ -class Websearch::WebsearchPrivate +struct Websearch::Internal { -public: - WebsearchPrivate(Extension *q) : q(q) {} - - bool deserialize(); - bool serialize(); - void restoreDefaults(); - QPointer widget; std::vector searchEngines; - - Extension *q; }; /** ***************************************************************************/ -bool Websearch::WebsearchPrivate::deserialize() { - - QFile file(QDir(QStandardPaths::writableLocation(QStandardPaths::DataLocation)) - .filePath(QString("%1.json").arg(q->Core::Extension::id))); - - if (!file.open(QIODevice::ReadOnly)) { - 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(); - 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; -} - - - -/** ***************************************************************************/ -bool Websearch::WebsearchPrivate::serialize() { - - QFile file(QDir(QStandardPaths::writableLocation(QStandardPaths::DataLocation)) - .filePath(QString("%1.json").arg(q->Core::Extension::id))); - - if (!file.open(QIODevice::WriteOnly)) { - qWarning() << qPrintable(QString("Could not open file: '%1'.").arg(file.fileName())); - return false; - } - - QJsonArray array; - - for ( const SearchEngine& searchEngine : searchEngines ) { - QJsonObject object; - object["name"] = searchEngine.name; - object["url"] = searchEngine.url; - object["trigger"] = searchEngine.trigger; - object["iconPath"] = searchEngine.iconPath; - object["enabled"] = searchEngine.enabled; - array.append(object); - } - - file.write(QJsonDocument(array).toJson()); - - return true; -} - - - -/** ***************************************************************************/ -void Websearch::WebsearchPrivate::restoreDefaults() { - /* Init std searches */ - searchEngines = defaultSearchEngines; - serialize(); - - if (!widget.isNull()) - widget->ui.tableView_searches->reset(); -} - - - -/** ***************************************************************************/ /** ***************************************************************************/ /** ***************************************************************************/ /** ***************************************************************************/ Websearch::Extension::Extension() : Core::Extension("org.albert.extension.websearch"), Core::QueryHandler(Core::Extension::id), - d(new WebsearchPrivate(this)) { + d(new Internal) { + + std::sort(validTlds.begin(), validTlds.end()); QString writableLocation = QStandardPaths::writableLocation(QStandardPaths::DataLocation); QFile dataFile(QDir(writableLocation).filePath(QString("%1.dat").arg(Core::Extension::id))); @@ -216,10 +331,10 @@ // Hmm what to do? // Serialize in json format - d->serialize(); + serialize(); - } else if (!d->deserialize()) - d->restoreDefaults(); + } else if (!deserialize()) + restoreDefaults(); } @@ -234,11 +349,25 @@ /** ***************************************************************************/ QWidget *Websearch::Extension::widget(QWidget *parent) { if (d->widget.isNull()){ + d->widget = new ConfigWidget(parent); - d->widget->ui.tableView_searches->setModel(this); + EnginesModel *enginesModel = new EnginesModel(d->searchEngines, + d->widget->ui.tableView_searches); + d->widget->ui.tableView_searches->setModel(enginesModel); + + // Serialize engines if anything changed + connect(enginesModel, &EnginesModel::dataChanged, + this, &Extension::serialize); + connect(enginesModel, &EnginesModel::rowsInserted, + this, &Extension::serialize); + connect(enginesModel, &EnginesModel::rowsRemoved, + this, &Extension::serialize); + connect(enginesModel, &EnginesModel::rowsMoved, + this, &Extension::serialize); + // TODO Fix all data() if least supported Qt supports its omittance connect(d->widget.data(), &ConfigWidget::restoreDefaults, - std::bind(&WebsearchPrivate::restoreDefaults, std::ref(d))); + this, &Extension::restoreDefaults); } return d->widget; } @@ -246,264 +375,124 @@ /** ***************************************************************************/ -void Websearch::Extension::handleQuery(Core::Query * query) { - for (const SearchEngine &se : d->searchEngines) - if (query->searchTerm().startsWith(se.trigger)) - query->addMatch(buildWebsearchItem(se, query->searchTerm().mid(se.trigger.size())), SHRT_MAX); +QStringList Websearch::Extension::triggers() const { + QStringList triggers; + for ( const SearchEngine& se : d->searchEngines ) + triggers.push_back(se.trigger); + return triggers; } /** ***************************************************************************/ -vector> Websearch::Extension::fallbacks(const QString & searchterm) { - vector> res; - for (const SearchEngine &se : d->searchEngines) - if (se.enabled) - res.push_back(buildWebsearchItem(se, searchterm)); - return res; -} - +void Websearch::Extension::handleQuery(Core::Query * query) { + if ( query->isTriggered() ) { + for (const SearchEngine &se : d->searchEngines) + if (query->searchTerm().startsWith(se.trigger)) + query->addMatch(buildWebsearchItem(se, query->searchTerm().mid(se.trigger.size())), SHRT_MAX); + } + else + { + QUrl url = QUrl::fromUserInput(query->searchTerm()); + + // Check syntax and TLD validity + if ( url.isValid() && // Check syntax + QRegularExpression(R"R(\S+\.\S+$)R").match(url.host()).hasMatch() && // Check if not an emty tld + std::binary_search(validTlds.begin(), validTlds.end(), // Check tld validiy + url.topLevelDomain().mid(1).toUpper().toLocal8Bit().constData()) ) { + + shared_ptr action = std::make_shared(); + action->setText("Open URL"); + action->setAction([url](){ + QDesktopServices::openUrl(url); + }); + + std::shared_ptr item = std::make_shared("valid_url"); + item->setText(QString("Open url in browser")); + item->setSubtext(QString("Visit %1").arg(url.authority())); + item->setCompletionString(query->searchTerm()); + QString icon = XdgIconLookup::iconPath("www"); + if (icon.isEmpty()) + icon = XdgIconLookup::iconPath("web-browser"); + if (icon.isEmpty()) + icon = XdgIconLookup::iconPath("emblem-web"); + if (icon.isEmpty()) + icon = ":favicon"; + item->setIconPath(icon); + item->setActions({action}); -/** ***************************************************************************/ -int Websearch::Extension::rowCount(const QModelIndex &) const { - return static_cast(d->searchEngines.size()); + query->addMatch(item, SHRT_MAX); + } + } } /** ***************************************************************************/ -int Websearch::Extension::columnCount(const QModelIndex &) const { - return static_cast(Section::Count); +vector> Websearch::Extension::fallbacks(const QString & searchterm) { + vector> res; + for (const SearchEngine &se : d->searchEngines) + if (se.enabled) + res.push_back(buildWebsearchItem(se, searchterm)); + return res; } /** ***************************************************************************/ -QVariant Websearch::Extension::headerData(int section, Qt::Orientation orientation, int role) const { - // No sanity check necessary since - if ( section<0 || static_cast(Section::Count)<=section ) - return QVariant(); - - - if (orientation == Qt::Horizontal){ - switch (static_cast
(section)) { - case Section::Enabled:{ - switch (role) { - case Qt::ToolTipRole: return "Enables the searchengine as fallback."; - default: return QVariant(); - } - } - case Section::Name:{ - switch (role) { - case Qt::DisplayRole: return "Name"; - case Qt::ToolTipRole: return "The name of the searchengine."; - default: return QVariant(); - } - - } - case Section::Trigger:{ - switch (role) { - case Qt::DisplayRole: return "Trigger"; - case Qt::ToolTipRole: return "The term that triggers this searchengine."; - default: return QVariant(); - } +bool Websearch::Extension::deserialize() { - } - case Section::URL:{ - switch (role) { - case Qt::DisplayRole: return "URL"; - case Qt::ToolTipRole: return "The URL of this searchengine. %s will be replaced by your searchterm."; - default: return QVariant(); - } + QFile file(QDir(QStandardPaths::writableLocation(QStandardPaths::DataLocation)) + .filePath(QString("%1.json").arg(Core::Extension::id))); - } - default: return QVariant(); - } + if (!file.open(QIODevice::ReadOnly)) { + qWarning() << qPrintable(QString("Could not open file: '%1'.").arg(file.fileName())); + return false; } - return QVariant(); -} - - -/** ***************************************************************************/ -QVariant Websearch::Extension::data(const QModelIndex &index, int role) const { - if (!index.isValid() - || index.row() >= static_cast(d->searchEngines.size()) - || index.column() >= static_cast(static_cast(Section::Count))) - return QVariant(); + QJsonArray array = QJsonDocument::fromJson(file.readAll()).array(); - switch (role) { - case Qt::DisplayRole: { - switch (static_cast
(index.column())) { - case Section::Name: return d->searchEngines[index.row()].name; - case Section::Trigger: return d->searchEngines[index.row()].trigger; - case Section::URL: return d->searchEngines[index.row()].url; - default: return QVariant(); - } - } - case Qt::EditRole: { - switch (static_cast
(index.column())) { - case Section::Name: return d->searchEngines[index.row()].name; - case Section::Trigger: return d->searchEngines[index.row()].trigger; - case Section::URL: return d->searchEngines[index.row()].url; - default: return QVariant(); - } - } - case Qt::DecorationRole: { - switch (static_cast
(index.column())) { - case Section::Name:{ - // Resizing request thounsands of repaints. Creating an icon for - // ever paint event is to expensive. Therefor maintain an icon cache - QString &iconPath = d->searchEngines[index.row()].iconPath; - decltype(iconCache)::iterator it = iconCache.find(iconPath); - if ( it != iconCache.end() ) - return it->second; - return iconCache.emplace(iconPath, QIcon(iconPath)).second; - } - default: return QVariant(); - } - } - case Qt::ToolTipRole: { - switch (static_cast
(index.column())) { - case Section::Enabled: return "Check to use as fallback"; - default: return "Double click to edit"; - } - } - case Qt::CheckStateRole: { - switch (static_cast
(index.column())) { - case Section::Enabled: return (d->searchEngines[index.row()].enabled)?Qt::Checked:Qt::Unchecked; - default: return QVariant(); - } - } - default: - return QVariant(); + SearchEngine searchEngine; + for ( const QJsonValue& value : array) { + QJsonObject object = value.toObject(); + 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(); + d->searchEngines.push_back(searchEngine); } -} - - -/** ***************************************************************************/ -bool Websearch::Extension::setData(const QModelIndex &index, const QVariant &value, int role) { - if (!index.isValid() - || index.row() >= static_cast(d->searchEngines.size()) - || index.column() >= static_cast(static_cast(Section::Count))) - return false; - - switch (role) { - case Qt::EditRole: { - if ( !value.canConvert(QMetaType::QString) ) - return false; - QString s = value.toString(); - switch (static_cast
(index.column())) { - case Section::Enabled: - return false; - case Section::Name: - d->searchEngines[index.row()].name = s; - dataChanged(index, index, QVector({Qt::DisplayRole})); - d->serialize(); - return true; - case Section::Trigger: - d->searchEngines[index.row()].trigger = s; - dataChanged(index, index, QVector({Qt::DisplayRole})); - d->serialize(); - return true; - case Section::URL: - d->searchEngines[index.row()].url = s; - dataChanged(index, index, QVector({Qt::DisplayRole})); - d->serialize(); - return true; - default: - return false; - } - } - case Qt::CheckStateRole: { - switch (static_cast
(index.column())) { - case Section::Enabled: - d->searchEngines[index.row()].enabled = value.toBool(); - dataChanged(index, index, QVector({Qt::CheckStateRole})); - d->serialize(); - return true; - default: - return false; - } - } - case Qt::DecorationRole: { - QFileInfo fileInfo(value.toString()); - QString newFilePath; - uint i = 0; - do { - // Build the new path in cache dir - newFilePath = QDir(QStandardPaths::writableLocation(QStandardPaths::CacheLocation)) - .filePath(QString("%1-%2.%3") - .arg(d->searchEngines[index.row()].name) - .arg(i++) - .arg(fileInfo.suffix())); - // Copy the file into cache dir - } while (!QFile::copy(fileInfo.filePath(), newFilePath)); - // Set the copied file as icon - d->searchEngines[index.row()].iconPath = newFilePath; - dataChanged(index, index, QVector({Qt::DecorationRole})); - d->serialize(); - iconCache.clear(); - return true; - } - default: - return false; - } - return false; + return true; } /** ***************************************************************************/ -Qt::ItemFlags Websearch::Extension::flags(const QModelIndex &index) const { - if (!index.isValid()) - return Qt::NoItemFlags; - - switch (static_cast
(index.column())) { - case Section::Enabled: - return Qt::ItemIsSelectable|Qt::ItemIsEnabled|Qt::ItemIsUserCheckable; - default: - return Qt::ItemIsSelectable|Qt::ItemIsEnabled|Qt::ItemIsEditable; - } -} - +bool Websearch::Extension::serialize() { + QFile file(QDir(QStandardPaths::writableLocation(QStandardPaths::DataLocation)) + .filePath(QString("%1.json").arg(Core::Extension::id))); -/** ***************************************************************************/ -bool Websearch::Extension::insertRows(int position, int rows, const QModelIndex &) { - if (position<0 || rows<1 || static_cast(d->searchEngines.size())searchEngines.insert(d->searchEngines.begin() + row, - SearchEngine({false, - "", - "", - ":default", - ""})); } - endInsertRows(); - - d->serialize(); - return true; -} - - - -/** ***************************************************************************/ -bool Websearch::Extension::removeRows(int position, int rows, const QModelIndex &) { - if (position<0 || rows<1 || static_cast(d->searchEngines.size())searchEngines.erase(d->searchEngines.begin()+position,d->searchEngines.begin()+(position+rows)); - endRemoveRows(); + for ( const SearchEngine& searchEngine : d->searchEngines ) { + QJsonObject object; + object["name"] = searchEngine.name; + object["url"] = searchEngine.url; + object["trigger"] = searchEngine.trigger; + object["iconPath"] = searchEngine.iconPath; + object["enabled"] = searchEngine.enabled; + array.append(object); + } - d->serialize(); + file.write(QJsonDocument(array).toJson()); return true; } @@ -511,23 +500,11 @@ /** ***************************************************************************/ -bool Websearch::Extension::moveRows(const QModelIndex &src, int srcRow, int cnt, const QModelIndex &dst, int dstRow) { - if (srcRow<0 || cnt<1 || dstRow<0 - || static_cast(d->searchEngines.size())(d->searchEngines.size()) tmp; - beginMoveRows(src, srcRow, srcRow+cnt-1, dst, dstRow); - tmp.insert(tmp.end(), make_move_iterator(d->searchEngines.begin()+srcRow), make_move_iterator(d->searchEngines.begin() + srcRow+cnt)); - d->searchEngines.erase(d->searchEngines.begin()+srcRow, d->searchEngines.begin() + srcRow+cnt); - const size_t finalDst = dstRow > srcRow ? dstRow - cnt : dstRow; - d->searchEngines.insert(d->searchEngines.begin()+finalDst , make_move_iterator(tmp.begin()), make_move_iterator(tmp.end())); - endMoveRows(); - - d->serialize(); +void Websearch::Extension::restoreDefaults() { + /* Init std searches */ + d->searchEngines = defaultSearchEngines; + serialize(); - return true; + if (!d->widget.isNull()) + d->widget->ui.tableView_searches->reset(); } - diff -Nru albert-0.10.3/src/plugins/websearch/src/main.h albert-0.11.1/src/plugins/websearch/src/main.h --- albert-0.10.3/src/plugins/websearch/src/main.h 2017-04-02 16:54:56.000000000 +0000 +++ albert-0.11.1/src/plugins/websearch/src/main.h 2017-04-16 11:17:45.000000000 +0000 @@ -15,7 +15,6 @@ // along with this program. If not, see . #pragma once -#include #include #include "extension.h" #include "queryhandler.h" @@ -23,11 +22,11 @@ namespace Websearch { -class WebsearchPrivate; +struct Internal; class ConfigWidget; class Extension final : - public QAbstractTableModel, // QObject + public QObject, public Core::Extension, public Core::QueryHandler, public Core::FallbackProvider @@ -40,32 +39,19 @@ Extension(); ~Extension(); - /* - * Implementation of extension interface - */ - QString name() const override { return "Websearch"; } QWidget *widget(QWidget *parent = nullptr) override; + QStringList triggers() const override; void handleQuery(Core::Query * query) override; std::vector> fallbacks(const QString &) override; - /* - * Implementation of extension interface - */ - - int rowCount(const QModelIndex & parent = QModelIndex()) const override; - int columnCount(const QModelIndex & parent = QModelIndex()) const override; - QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; - QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const override; - bool setData(const QModelIndex & index, const QVariant & value, int role = Qt::EditRole) override; - Qt::ItemFlags flags(const QModelIndex & index) const override; - bool insertRows (int position, int rows, const QModelIndex & parent = QModelIndex()) override; - bool removeRows (int position, int rows, const QModelIndex & parent = QModelIndex()) override; - bool moveRows(const QModelIndex &sourceRow, int srcRow, int cnt, const QModelIndex & dst, int destinationChild) override; - private: - std::unique_ptr d; + bool deserialize(); + bool serialize(); + void restoreDefaults(); + + std::unique_ptr d; }; Binary files /tmp/tmplsmo3b/hmJCwrRMqo/albert-0.10.3/v0.8.11.gif and /tmp/tmplsmo3b/0cNe84Uf9J/albert-0.11.1/v0.8.11.gif differ