diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index d27fa2aa..98266443 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -81,10 +81,25 @@ dependency-updates:
# Stage: BUILD
+build-qml:
+ tags:
+ - small
+ only:
+ - branches
+ stage: build
+ artifacts:
+ name: "bridge-qml-$CI_COMMIT_SHORT_SHA"
+ expire_in: 1 day
+ paths:
+ - bridge_qml.tgz
+ script:
+ - cd internal/frontend/qml
+ - tar -cvzf ../../../bridge_qml.tgz ./*
+
.build-base:
stage: build
only:
- - branches
+ - manual
before_script:
- mkdir -p .cache/bin
- export PATH=$(pwd)/.cache/bin:$PATH
@@ -118,26 +133,6 @@ build-linux-qa:
paths:
- bridge_*.tgz
-build-ie-linux:
- extends: .build-base
- script:
- - make build-ie
- artifacts:
- name: "ie-linux-$CI_COMMIT_SHORT_SHA"
- paths:
- - ie_*.tgz
-
-build-ie-linux-qa:
- extends: .build-base
- only:
- - web
- script:
- - BUILD_TAGS="build_qa" make build-ie
- artifacts:
- name: "ie-linux-qa-$CI_COMMIT_SHORT_SHA"
- paths:
- - ie_*.tgz
-
.build-darwin-base:
extends: .build-base
before_script:
diff --git a/Makefile b/Makefile
index cf0a5b57..516c687c 100644
--- a/Makefile
+++ b/Makefile
@@ -230,7 +230,6 @@ test: gofiles
./internal/cookies/... \
./internal/crash/... \
./internal/events/... \
- ./internal/frontend/autoconfig/... \
./internal/frontend/cli/... \
./internal/imap/... \
./internal/importexport/... \
diff --git a/cmd/Import-Export/main.go b/cmd/Import-Export/main.go
deleted file mode 100644
index 868c55b1..00000000
--- a/cmd/Import-Export/main.go
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-package main
-
-import (
- "os"
-
- "github.com/ProtonMail/proton-bridge/internal/app/base"
- "github.com/ProtonMail/proton-bridge/internal/app/ie"
- "github.com/sirupsen/logrus"
-)
-
-const (
- appName = "ProtonMail Import-Export app"
- appUsage = "Import and export messages to/from your ProtonMail account"
- configName = "importExport"
- updateURLName = "ie"
- keychainName = "import-export-app"
- cacheVersion = "c11"
-)
-
-func main() {
- base, err := base.New(
- appName,
- appUsage,
- configName,
- updateURLName,
- keychainName,
- cacheVersion,
- )
- if err != nil {
- logrus.WithError(err).Fatal("Failed to create app base")
- }
- // Other instance already running.
- if base == nil {
- return
- }
-
- if err := ie.New(base).Run(os.Args); err != nil {
- logrus.WithError(err).Fatal("IE exited with error")
- }
-}
diff --git a/internal/app/ie/ie.go b/internal/app/ie/ie.go
deleted file mode 100644
index e6348311..00000000
--- a/internal/app/ie/ie.go
+++ /dev/null
@@ -1,110 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// Package ie implements the ie CLI application.
-package ie
-
-import (
- "time"
-
- "github.com/ProtonMail/proton-bridge/internal/api"
- "github.com/ProtonMail/proton-bridge/internal/app/base"
- "github.com/ProtonMail/proton-bridge/internal/config/settings"
- "github.com/ProtonMail/proton-bridge/internal/constants"
- "github.com/ProtonMail/proton-bridge/internal/frontend"
- "github.com/ProtonMail/proton-bridge/internal/frontend/types"
- "github.com/ProtonMail/proton-bridge/internal/importexport"
- "github.com/sirupsen/logrus"
- "github.com/urfave/cli/v2"
-)
-
-func New(b *base.Base) *cli.App {
- return b.NewApp(run)
-}
-
-func run(b *base.Base, c *cli.Context) error {
- ie := importexport.New(b.Locations, b.Cache, b.CrashHandler, b.Listener, b.CM, b.Creds)
-
- go func() {
- defer b.CrashHandler.HandlePanic()
- api.NewAPIServer(b.Settings, b.Listener).ListenAndServe()
- }()
-
- var frontendMode string
-
- switch {
- case c.Bool(base.FlagCLI):
- frontendMode = "cli"
- default:
- frontendMode = "qt"
- }
-
- // We want to remove old versions if the app exits successfully.
- b.AddTeardownAction(b.Versioner.RemoveOldVersions)
-
- // We want cookies to be saved to disk so they are loaded the next time.
- b.AddTeardownAction(b.CookieJar.PersistCookies)
-
- f := frontend.NewImportExport(
- constants.Version,
- constants.BuildVersion,
- b.Name,
- frontendMode,
- b.CrashHandler,
- b.Locations,
- b.Settings,
- b.Listener,
- b.Updater,
- ie,
- b,
- )
-
- // Watch for updates routine
- go func() {
- ticker := time.NewTicker(time.Hour)
-
- for {
- checkAndHandleUpdate(b.Updater, f, b.Settings.GetBool(settings.AutoUpdateKey))
- <-ticker.C
- }
- }()
-
- return f.Loop()
-}
-
-func checkAndHandleUpdate(u types.Updater, f frontend.Frontend, autoUpdate bool) { //nolint[unparam]
- log := logrus.WithField("pkg", "app/ie")
- version, err := u.Check()
- if err != nil {
- log.WithError(err).Error("An error occurred while checking for updates")
- return
- }
-
- f.WaitUntilFrontendIsReady()
-
- // Update links in UI
- f.SetVersion(version)
-
- if !u.IsUpdateApplicable(version) {
- log.Info("No need to update")
- return
- }
-
- log.WithField("version", version.Version).Info("An update is available")
-
- f.NotifyManualUpdate(version, u.CanInstall(version))
-}
diff --git a/internal/frontend/autoconfig/applemail.go b/internal/frontend/autoconfig/applemail.go
deleted file mode 100644
index b125bd38..00000000
--- a/internal/frontend/autoconfig/applemail.go
+++ /dev/null
@@ -1,131 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// +build darwin
-
-package autoconfig
-
-import (
- "io/ioutil"
- "os"
- "os/exec"
- "path/filepath"
- "strconv"
- "strings"
- "time"
-
- "github.com/ProtonMail/proton-bridge/internal/bridge"
- "github.com/ProtonMail/proton-bridge/internal/config/useragent"
- "github.com/ProtonMail/proton-bridge/internal/frontend/types"
- "github.com/ProtonMail/proton-bridge/pkg/mobileconfig"
-)
-
-const (
- bigSurPreferncesPane = "/System/Library/PreferencePanes/Profiles.prefPane"
-)
-
-func init() { //nolint[gochecknoinit]
- available = append(available, &appleMail{})
-}
-
-type appleMail struct{}
-
-func (c *appleMail) Name() string {
- return "Apple Mail"
-}
-
-func (c *appleMail) Configure(imapPort, smtpPort int, imapSSL, smtpSSL bool, user types.User, addressIndex int) error {
- mc := prepareMobileConfig(imapPort, smtpPort, imapSSL, smtpSSL, user, addressIndex)
-
- confPath, err := saveConfigTemporarily(mc)
- if err != nil {
- return err
- }
-
- if useragent.IsBigSurOrNewer() {
- return exec.Command("open", bigSurPreferncesPane, confPath).Run() //nolint[gosec] G204: open command is safe, mobileconfig is generated by us
- }
-
- return exec.Command("open", confPath).Run() //nolint[gosec] G204: open command is safe, mobileconfig is generated by us
-}
-
-func prepareMobileConfig(imapPort, smtpPort int, imapSSL, smtpSSL bool, user types.User, addressIndex int) *mobileconfig.Config {
- var addresses string
- var displayName string
-
- if user.IsCombinedAddressMode() {
- displayName = user.GetPrimaryAddress()
- addresses = strings.Join(user.GetAddresses(), ",")
- } else {
- for idx, address := range user.GetAddresses() {
- if idx == addressIndex {
- displayName = address
- break
- }
- }
- addresses = displayName
- }
-
- timestamp := strconv.FormatInt(time.Now().Unix(), 10)
-
- return &mobileconfig.Config{
- EmailAddress: addresses,
- DisplayName: displayName,
- Identifier: "protonmail " + displayName + timestamp,
- IMAP: &mobileconfig.IMAP{
- Hostname: bridge.Host,
- Port: imapPort,
- TLS: imapSSL,
- Username: displayName,
- Password: user.GetBridgePassword(),
- },
- SMTP: &mobileconfig.SMTP{
- Hostname: bridge.Host,
- Port: smtpPort,
- TLS: smtpSSL,
- Username: displayName,
- },
- }
-}
-
-func saveConfigTemporarily(mc *mobileconfig.Config) (fname string, err error) {
- dir, err := ioutil.TempDir("", "protonmail-autoconfig")
- if err != nil {
- return
- }
-
- // Make sure the temporary file is deleted.
- go (func() {
- <-time.After(10 * time.Minute)
- _ = os.RemoveAll(dir)
- })()
-
- // Make sure the file is only readable for the current user.
- fname = filepath.Clean(filepath.Join(dir, "protonmail.mobileconfig"))
- f, err := os.OpenFile(fname, os.O_RDWR|os.O_CREATE, 0600)
- if err != nil {
- return
- }
-
- if err = mc.WriteOut(f); err != nil {
- _ = f.Close()
- return
- }
- _ = f.Close()
-
- return
-}
diff --git a/internal/frontend/autoconfig/autoconfig.go b/internal/frontend/autoconfig/autoconfig.go
deleted file mode 100644
index 254782bb..00000000
--- a/internal/frontend/autoconfig/autoconfig.go
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// Package autoconfig provides automatic config of IMAP and SMTP.
-// For now only for Apple Mail.
-package autoconfig
-
-import "github.com/ProtonMail/proton-bridge/internal/frontend/types"
-
-type AutoConfig interface {
- Name() string
- Configure(imapPort int, smtpPort int, imapSSl, smtpSSL bool, user types.User, addressIndex int) error
-}
-
-var available []AutoConfig //nolint[gochecknoglobals]
-
-func Available() []AutoConfig {
- return available
-}
diff --git a/internal/frontend/cli-ie/account_utils.go b/internal/frontend/cli-ie/account_utils.go
deleted file mode 100644
index f99f28ac..00000000
--- a/internal/frontend/cli-ie/account_utils.go
+++ /dev/null
@@ -1,100 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-package cliie
-
-import (
- "fmt"
- "strconv"
- "strings"
-
- "github.com/ProtonMail/proton-bridge/internal/frontend/types"
- "github.com/abiosoft/ishell"
-)
-
-// completeUsernames is a helper to complete usernames as the user types.
-func (f *frontendCLI) completeUsernames(args []string) (usernames []string) {
- if len(args) > 1 {
- return
- }
- arg := ""
- if len(args) == 1 {
- arg = args[0]
- }
- for _, user := range f.ie.GetUsers() {
- if strings.HasPrefix(strings.ToLower(user.Username()), strings.ToLower(arg)) {
- usernames = append(usernames, user.Username())
- }
- }
- return
-}
-
-// noAccountWrapper is a decorator for functions which need any account to be properly functional.
-func (f *frontendCLI) noAccountWrapper(callback func(*ishell.Context)) func(*ishell.Context) {
- return func(c *ishell.Context) {
- users := f.ie.GetUsers()
- if len(users) == 0 {
- f.Println("No active accounts. Please add account to continue.")
- } else {
- callback(c)
- }
- }
-}
-
-func (f *frontendCLI) askUserByIndexOrName(c *ishell.Context) types.User {
- user := f.getUserByIndexOrName("")
- if user != nil {
- return user
- }
-
- numberOfAccounts := len(f.ie.GetUsers())
- indexRange := fmt.Sprintf("number between 0 and %d", numberOfAccounts-1)
- if len(c.Args) == 0 {
- f.Printf("Please choose %s or username.\n", indexRange)
- return nil
- }
- arg := c.Args[0]
- user = f.getUserByIndexOrName(arg)
- if user == nil {
- f.Printf("Wrong input '%s'. Choose %s or username.\n", bold(arg), indexRange)
- return nil
- }
- return user
-}
-
-func (f *frontendCLI) getUserByIndexOrName(arg string) types.User {
- users := f.ie.GetUsers()
- numberOfAccounts := len(users)
- if numberOfAccounts == 0 {
- return nil
- }
- if numberOfAccounts == 1 {
- return users[0]
- }
- if index, err := strconv.Atoi(arg); err == nil {
- if index < 0 || index >= numberOfAccounts {
- return nil
- }
- return users[index]
- }
- for _, user := range users {
- if user.Username() == arg {
- return user
- }
- }
- return nil
-}
diff --git a/internal/frontend/cli-ie/accounts.go b/internal/frontend/cli-ie/accounts.go
deleted file mode 100644
index b98c0e19..00000000
--- a/internal/frontend/cli-ie/accounts.go
+++ /dev/null
@@ -1,154 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-package cliie
-
-import (
- "context"
- "strings"
-
- "github.com/abiosoft/ishell"
-)
-
-func (f *frontendCLI) listAccounts(c *ishell.Context) {
- spacing := "%-2d: %-20s (%-15s, %-15s)\n"
- f.Printf(bold(strings.ReplaceAll(spacing, "d", "s")), "#", "account", "status", "address mode")
- for idx, user := range f.ie.GetUsers() {
- connected := "disconnected"
- if user.IsConnected() {
- connected = "connected"
- }
- mode := "split"
- if user.IsCombinedAddressMode() {
- mode = "combined"
- }
- f.Printf(spacing, idx, user.Username(), connected, mode)
- }
- f.Println()
-}
-
-func (f *frontendCLI) loginAccount(c *ishell.Context) { // nolint[funlen]
- f.ShowPrompt(false)
- defer f.ShowPrompt(true)
-
- loginName := ""
- if len(c.Args) > 0 {
- user := f.getUserByIndexOrName(c.Args[0])
- if user != nil {
- loginName = user.GetPrimaryAddress()
- }
- }
-
- if loginName == "" {
- loginName = f.readStringInAttempts("Username", c.ReadLine, isNotEmpty)
- if loginName == "" {
- return
- }
- } else {
- f.Println("Username:", loginName)
- }
-
- password := f.readStringInAttempts("Password", c.ReadPassword, isNotEmpty)
- if password == "" {
- return
- }
-
- f.Println("Authenticating ... ")
- client, auth, err := f.ie.Login(loginName, []byte(password))
- if err != nil {
- f.processAPIError(err)
- return
- }
-
- if auth.HasTwoFactor() {
- twoFactor := f.readStringInAttempts("Two factor code", c.ReadLine, isNotEmpty)
- if twoFactor == "" {
- return
- }
-
- err = client.Auth2FA(context.Background(), twoFactor)
- if err != nil {
- f.processAPIError(err)
- return
- }
- }
-
- mailboxPassword := password
- if auth.HasMailboxPassword() {
- mailboxPassword = f.readStringInAttempts("Mailbox password", c.ReadPassword, isNotEmpty)
- }
- if mailboxPassword == "" {
- return
- }
-
- f.Println("Adding account ...")
- user, err := f.ie.FinishLogin(client, auth, []byte(mailboxPassword))
- if err != nil {
- log.WithField("username", loginName).WithError(err).Error("Login was unsuccessful")
- f.Println("Adding account was unsuccessful:", err)
- return
- }
-
- f.Printf("Account %s was added successfully.\n", bold(user.Username()))
-}
-
-func (f *frontendCLI) logoutAccount(c *ishell.Context) {
- f.ShowPrompt(false)
- defer f.ShowPrompt(true)
-
- user := f.askUserByIndexOrName(c)
- if user == nil {
- return
- }
- if f.yesNoQuestion("Are you sure you want to logout account " + bold(user.Username())) {
- if err := user.Logout(); err != nil {
- f.printAndLogError("Logging out failed: ", err)
- }
- }
-}
-
-func (f *frontendCLI) deleteAccount(c *ishell.Context) {
- f.ShowPrompt(false)
- defer f.ShowPrompt(true)
-
- user := f.askUserByIndexOrName(c)
- if user == nil {
- return
- }
- if f.yesNoQuestion("Are you sure you want to " + bold("remove account "+user.Username())) {
- clearCache := f.yesNoQuestion("Do you want to remove cache for this account")
- if err := f.ie.DeleteUser(user.ID(), clearCache); err != nil {
- f.printAndLogError("Cannot delete account: ", err)
- return
- }
- }
-}
-
-func (f *frontendCLI) deleteAccounts(c *ishell.Context) {
- f.ShowPrompt(false)
- defer f.ShowPrompt(true)
-
- if !f.yesNoQuestion("Do you really want remove all accounts") {
- return
- }
- for _, user := range f.ie.GetUsers() {
- if err := f.ie.DeleteUser(user.ID(), false); err != nil {
- f.printAndLogError("Cannot delete account ", user.Username(), ": ", err)
- }
- }
- c.Println("Keychain cleared")
-}
diff --git a/internal/frontend/cli-ie/frontend.go b/internal/frontend/cli-ie/frontend.go
deleted file mode 100644
index d945605e..00000000
--- a/internal/frontend/cli-ie/frontend.go
+++ /dev/null
@@ -1,224 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// Package cliie provides CLI interface of the Import-Export app.
-package cliie
-
-import (
- "github.com/ProtonMail/proton-bridge/internal/events"
- "github.com/ProtonMail/proton-bridge/internal/frontend/types"
- "github.com/ProtonMail/proton-bridge/internal/locations"
- "github.com/ProtonMail/proton-bridge/internal/updater"
- "github.com/ProtonMail/proton-bridge/pkg/listener"
-
- "github.com/abiosoft/ishell"
- "github.com/sirupsen/logrus"
-)
-
-var (
- log = logrus.WithField("pkg", "frontend/cli-ie") //nolint[gochecknoglobals]
-)
-
-type frontendCLI struct {
- *ishell.Shell
-
- locations *locations.Locations
- eventListener listener.Listener
- updater types.Updater
- ie types.ImportExporter
-
- restarter types.Restarter
-}
-
-// New returns a new CLI frontend configured with the given options.
-func New( //nolint[funlen]
- panicHandler types.PanicHandler,
-
- locations *locations.Locations,
- eventListener listener.Listener,
- updater types.Updater,
- ie types.ImportExporter,
- restarter types.Restarter,
-) *frontendCLI { //nolint[golint]
- fe := &frontendCLI{
- Shell: ishell.New(),
-
- locations: locations,
- eventListener: eventListener,
- updater: updater,
- ie: ie,
-
- restarter: restarter,
- }
-
- // Clear commands.
- clearCmd := &ishell.Cmd{Name: "clear",
- Help: "remove stored accounts and preferences. (alias: cl)",
- Aliases: []string{"cl"},
- }
- clearCmd.AddCmd(&ishell.Cmd{Name: "accounts",
- Help: "remove all accounts from keychain. (aliases: a, k, keychain)",
- Aliases: []string{"a", "k", "keychain"},
- Func: fe.deleteAccounts,
- })
- fe.AddCmd(clearCmd)
-
- // Check commands.
- checkCmd := &ishell.Cmd{Name: "check", Help: "check internet connection or new version."}
- checkCmd.AddCmd(&ishell.Cmd{Name: "updates",
- Help: "check for Import-Export updates. (aliases: u, v, version)",
- Aliases: []string{"u", "version", "v"},
- Func: fe.checkUpdates,
- })
- fe.AddCmd(checkCmd)
-
- // Print info commands.
- fe.AddCmd(&ishell.Cmd{Name: "log-dir",
- Help: "print path to directory with logs. (aliases: log, logs)",
- Aliases: []string{"log", "logs"},
- Func: fe.printLogDir,
- })
- fe.AddCmd(&ishell.Cmd{Name: "manual",
- Help: "print URL with instructions. (alias: man)",
- Aliases: []string{"man"},
- Func: fe.printManual,
- })
- fe.AddCmd(&ishell.Cmd{Name: "credits",
- Help: "print used resources.",
- Func: fe.printCredits,
- })
-
- // Account commands.
- fe.AddCmd(&ishell.Cmd{Name: "list",
- Help: "print the list of accounts. (aliases: l, ls)",
- Func: fe.noAccountWrapper(fe.listAccounts),
- Aliases: []string{"l", "ls"},
- })
- fe.AddCmd(&ishell.Cmd{Name: "login",
- Help: "login procedure to add or connect account. Optionally use index or account as parameter. (aliases: a, add, con, connect)",
- Func: fe.loginAccount,
- Aliases: []string{"add", "a", "con", "connect"},
- Completer: fe.completeUsernames,
- })
- fe.AddCmd(&ishell.Cmd{Name: "logout",
- Help: "disconnect the account. Use index or account name as parameter. (aliases: d, disconnect)",
- Func: fe.noAccountWrapper(fe.logoutAccount),
- Aliases: []string{"d", "disconnect"},
- Completer: fe.completeUsernames,
- })
- fe.AddCmd(&ishell.Cmd{Name: "delete",
- Help: "remove the account from keychain. Use index or account name as parameter. (aliases: del, rm, remove)",
- Func: fe.noAccountWrapper(fe.deleteAccount),
- Aliases: []string{"del", "rm", "remove"},
- Completer: fe.completeUsernames,
- })
-
- // Import-Export commands.
- importCmd := &ishell.Cmd{Name: "import",
- Help: "import messages. (alias: imp)",
- Aliases: []string{"imp"},
- }
- importCmd.AddCmd(&ishell.Cmd{Name: "local",
- Help: "import local messages. (aliases: loc)",
- Func: fe.noAccountWrapper(fe.importLocalMessages),
- Aliases: []string{"loc"},
- })
- importCmd.AddCmd(&ishell.Cmd{Name: "remote",
- Help: "import remote messages. (aliases: rem)",
- Func: fe.noAccountWrapper(fe.importRemoteMessages),
- Aliases: []string{"rem"},
- })
- fe.AddCmd(importCmd)
-
- exportCmd := &ishell.Cmd{Name: "export",
- Help: "export messages. (alias: exp)",
- Aliases: []string{"exp"},
- }
- exportCmd.AddCmd(&ishell.Cmd{Name: "eml",
- Help: "export messages to eml files.",
- Func: fe.noAccountWrapper(fe.exportMessagesToEML),
- })
- exportCmd.AddCmd(&ishell.Cmd{Name: "mbox",
- Help: "export messages to mbox files.",
- Func: fe.noAccountWrapper(fe.exportMessagesToMBOX),
- })
- fe.AddCmd(exportCmd)
-
- // System commands.
- fe.AddCmd(&ishell.Cmd{Name: "restart",
- Help: "restart the Import-Export app.",
- Func: fe.restart,
- })
-
- go func() {
- defer panicHandler.HandlePanic()
- fe.watchEvents()
- }()
- return fe
-}
-
-func (f *frontendCLI) watchEvents() {
- errorCh := f.eventListener.ProvideChannel(events.ErrorEvent)
- credentialsErrorCh := f.eventListener.ProvideChannel(events.CredentialsErrorEvent)
- internetOffCh := f.eventListener.ProvideChannel(events.InternetOffEvent)
- internetOnCh := f.eventListener.ProvideChannel(events.InternetOnEvent)
- addressChangedLogoutCh := f.eventListener.ProvideChannel(events.AddressChangedLogoutEvent)
- logoutCh := f.eventListener.ProvideChannel(events.LogoutEvent)
- certIssue := f.eventListener.ProvideChannel(events.TLSCertIssue)
- for {
- select {
- case errorDetails := <-errorCh:
- f.Println("Import-Export failed:", errorDetails)
- case <-credentialsErrorCh:
- f.notifyCredentialsError()
- case <-internetOffCh:
- f.notifyInternetOff()
- case <-internetOnCh:
- f.notifyInternetOn()
- case address := <-addressChangedLogoutCh:
- f.notifyLogout(address)
- case userID := <-logoutCh:
- user, err := f.ie.GetUser(userID)
- if err != nil {
- return
- }
- f.notifyLogout(user.Username())
- case <-certIssue:
- f.notifyCertIssue()
- }
- }
-}
-
-// Loop starts the frontend loop with an interactive shell.
-func (f *frontendCLI) Loop() error {
- f.Print(`
-Welcome to ProtonMail Import-Export app interactive shell
-
-WARNING: The CLI is an experimental feature and does not yet cover all functionality.
- `)
- f.Run()
- return nil
-}
-
-func (f *frontendCLI) NotifyManualUpdate(update updater.VersionInfo, canInstall bool) {
- // NOTE: Save the update somewhere so that it can be installed when user chooses "install now".
-}
-
-func (f *frontendCLI) WaitUntilFrontendIsReady() {}
-func (f *frontendCLI) SetVersion(version updater.VersionInfo) {}
-func (f *frontendCLI) NotifySilentUpdateInstalled() {}
-func (f *frontendCLI) NotifySilentUpdateError(err error) {}
diff --git a/internal/frontend/cli-ie/importexport.go b/internal/frontend/cli-ie/importexport.go
deleted file mode 100644
index 3463c4c0..00000000
--- a/internal/frontend/cli-ie/importexport.go
+++ /dev/null
@@ -1,232 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-package cliie
-
-import (
- "fmt"
- "os"
- "strings"
- "time"
-
- "github.com/ProtonMail/proton-bridge/internal/frontend/types"
- "github.com/ProtonMail/proton-bridge/internal/transfer"
- "github.com/ProtonMail/proton-bridge/pkg/pmapi"
- "github.com/abiosoft/ishell"
-)
-
-func (f *frontendCLI) importLocalMessages(c *ishell.Context) {
- f.ShowPrompt(false)
- defer f.ShowPrompt(true)
-
- user, path := f.getUserAndPath(c, false)
- if user == nil || path == "" {
- return
- }
-
- t, err := f.ie.GetLocalImporter(user.Username(), user.GetPrimaryAddress(), path)
- f.transfer(t, err, false, true)
-}
-
-func (f *frontendCLI) importRemoteMessages(c *ishell.Context) {
- f.ShowPrompt(false)
- defer f.ShowPrompt(true)
-
- user := f.askUserByIndexOrName(c)
- if user == nil {
- return
- }
-
- username := f.readStringInAttempts("IMAP username", c.ReadLine, isNotEmpty)
- if username == "" {
- return
- }
- password := f.readStringInAttempts("IMAP password", c.ReadPassword, isNotEmpty)
- if password == "" {
- return
- }
- host := f.readStringInAttempts("IMAP host", c.ReadLine, isNotEmpty)
- if host == "" {
- return
- }
- port := f.readStringInAttempts("IMAP port", c.ReadLine, isNotEmpty)
- if port == "" {
- return
- }
-
- t, err := f.ie.GetRemoteImporter(user.Username(), user.GetPrimaryAddress(), username, password, host, port)
- f.transfer(t, err, false, true)
-}
-
-func (f *frontendCLI) exportMessagesToEML(c *ishell.Context) {
- f.ShowPrompt(false)
- defer f.ShowPrompt(true)
-
- user, path := f.getUserAndPath(c, true)
- if user == nil || path == "" {
- return
- }
-
- t, err := f.ie.GetEMLExporter(user.Username(), user.GetPrimaryAddress(), path)
- f.transfer(t, err, true, false)
-}
-
-func (f *frontendCLI) exportMessagesToMBOX(c *ishell.Context) {
- f.ShowPrompt(false)
- defer f.ShowPrompt(true)
-
- user, path := f.getUserAndPath(c, true)
- if user == nil || path == "" {
- return
- }
-
- t, err := f.ie.GetMBOXExporter(user.Username(), user.GetPrimaryAddress(), path)
- f.transfer(t, err, true, false)
-}
-
-func (f *frontendCLI) getUserAndPath(c *ishell.Context, createPath bool) (types.User, string) {
- user := f.askUserByIndexOrName(c)
- if user == nil {
- return nil, ""
- }
-
- path := f.readStringInAttempts("Path of EML and MBOX files", c.ReadLine, isNotEmpty)
- if path == "" {
- return nil, ""
- }
-
- if createPath {
- _ = os.Mkdir(path, os.ModePerm)
- }
-
- return user, path
-}
-
-func (f *frontendCLI) transfer(t *transfer.Transfer, err error, askSkipEncrypted bool, askGlobalMailbox bool) {
- if err != nil {
- f.printAndLogError("Failed to init transferrer: ", err)
- return
- }
-
- if askSkipEncrypted {
- skipEncryptedMessages := f.yesNoQuestion("Skip encrypted messages")
- t.SetSkipEncryptedMessages(skipEncryptedMessages)
- }
-
- if !f.setTransferRules(t) {
- return
- }
-
- if askGlobalMailbox {
- if err := f.setTransferGlobalMailbox(t); err != nil {
- f.printAndLogError("Failed to create global mailbox: ", err)
- return
- }
- }
-
- progress := t.Start()
- for range progress.GetUpdateChannel() {
- f.printTransferProgress(progress)
- }
- f.printTransferResult(progress)
-}
-
-func (f *frontendCLI) setTransferGlobalMailbox(t *transfer.Transfer) error {
- labelName := fmt.Sprintf("Imported %s", time.Now().Format("Jan-02-2006 15:04"))
-
- useGlobalLabel := f.yesNoQuestion("Use global label " + labelName)
- if !useGlobalLabel {
- return nil
- }
-
- globalMailbox, err := t.CreateTargetMailbox(transfer.Mailbox{
- Name: labelName,
- Color: pmapi.LabelColors[0],
- IsExclusive: false,
- })
- if err != nil {
- return err
- }
-
- t.SetGlobalMailbox(&globalMailbox)
- return nil
-}
-
-func (f *frontendCLI) setTransferRules(t *transfer.Transfer) bool {
- f.Println("Rules:")
- for _, rule := range t.GetRules() {
- if !rule.Active {
- continue
- }
- targets := strings.Join(rule.TargetMailboxNames(), ", ")
- if rule.HasTimeLimit() {
- f.Printf(" %-30s → %s (%s - %s)\n", rule.SourceMailbox.Name, targets, rule.FromDate(), rule.ToDate())
- } else {
- f.Printf(" %-30s → %s\n", rule.SourceMailbox.Name, targets)
- }
- }
-
- return f.yesNoQuestion("Proceed")
-}
-
-func (f *frontendCLI) printTransferProgress(progress *transfer.Progress) {
- counts := progress.GetCounts()
- if counts.Total != 0 {
- f.Println(fmt.Sprintf(
- "Progress update: %d (%d / %d) / %d, skipped: %d, failed: %d",
- counts.Imported,
- counts.Exported,
- counts.Added,
- counts.Total,
- counts.Skipped,
- counts.Failed,
- ))
- }
-
- if progress.IsPaused() {
- f.Printf("Transfer is paused bacause %s", progress.PauseReason())
- if !f.yesNoQuestion("Continue (y) or stop (n)") {
- progress.Stop()
- }
- }
-}
-
-func (f *frontendCLI) printTransferResult(progress *transfer.Progress) {
- err := progress.GetFatalError()
- if err != nil {
- f.Println("Transfer failed: " + err.Error())
- return
- }
-
- statuses := progress.GetFailedMessages()
- if len(statuses) == 0 {
- f.Println("Transfer finished!")
- return
- }
-
- f.Println("Transfer finished with errors:")
- for _, messageStatus := range statuses {
- f.Printf(
- " %-17s | %-30s | %-30s\n %s: %s\n",
- messageStatus.Time.Format("Jan 02 2006 15:04"),
- messageStatus.From,
- messageStatus.Subject,
- messageStatus.SourceID,
- messageStatus.GetErrorMessage(),
- )
- }
-}
diff --git a/internal/frontend/cli-ie/system.go b/internal/frontend/cli-ie/system.go
deleted file mode 100644
index bcc1c69d..00000000
--- a/internal/frontend/cli-ie/system.go
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-package cliie
-
-import (
- "github.com/abiosoft/ishell"
-)
-
-func (f *frontendCLI) restart(c *ishell.Context) {
- if f.yesNoQuestion("Are you sure you want to restart the Import-Export app") {
- f.Println("Restarting the Import-Export app...")
- f.restarter.SetToRestart()
- f.Stop()
- }
-}
-
-func (f *frontendCLI) printLogDir(c *ishell.Context) {
- if path, err := f.locations.ProvideLogsPath(); err != nil {
- f.Println("Failed to determine location of log files")
- } else {
- f.Println("Log files are stored in\n\n ", path)
- }
-}
-
-func (f *frontendCLI) printManual(c *ishell.Context) {
- f.Println("More instructions about the Import-Export app can be found at\n\n https://protonmail.com/support/categories/import-export/")
-}
diff --git a/internal/frontend/cli-ie/updates.go b/internal/frontend/cli-ie/updates.go
deleted file mode 100644
index 332b58fe..00000000
--- a/internal/frontend/cli-ie/updates.go
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-package cliie
-
-import (
- "strings"
-
- "github.com/ProtonMail/proton-bridge/internal/importexport"
- "github.com/abiosoft/ishell"
-)
-
-func (f *frontendCLI) checkUpdates(c *ishell.Context) {
- f.Println("Your version is up to date.")
-}
-
-func (f *frontendCLI) printCredits(c *ishell.Context) {
- for _, pkg := range strings.Split(importexport.Credits, ";") {
- f.Println(pkg)
- }
-}
diff --git a/internal/frontend/cli-ie/utils.go b/internal/frontend/cli-ie/utils.go
deleted file mode 100644
index 361303bd..00000000
--- a/internal/frontend/cli-ie/utils.go
+++ /dev/null
@@ -1,128 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-package cliie
-
-import (
- "strings"
-
- "github.com/ProtonMail/proton-bridge/pkg/pmapi"
- "github.com/fatih/color"
-)
-
-const (
- maxInputRepeat = 2
-)
-
-var (
- bold = color.New(color.Bold).SprintFunc() //nolint[gochecknoglobals]
-)
-
-func isNotEmpty(val string) bool {
- return val != ""
-}
-
-func (f *frontendCLI) yesNoQuestion(question string) bool {
- f.Print(question, "? yes/"+bold("no")+": ")
- yes := "yes"
- answer := strings.ToLower(f.ReadLine())
- for i := 0; i < len(answer); i++ {
- if i >= len(yes) || answer[i] != yes[i] {
- return false // Everything else is false.
- }
- }
- return len(answer) > 0 // Empty is false.
-}
-
-func (f *frontendCLI) readStringInAttempts(title string, readFunc func() string, isOK func(string) bool) (value string) {
- f.Printf("%s: ", title)
- value = readFunc()
- title = strings.ToLower(string(title[0])) + title[1:]
- for i := 0; !isOK(value); i++ {
- if i >= maxInputRepeat {
- f.Println("Too many attempts")
- return ""
- }
- f.Printf("Please fill %s: ", title)
- value = readFunc()
- }
- return
-}
-
-func (f *frontendCLI) printAndLogError(args ...interface{}) {
- log.Error(args...)
- f.Println(args...)
-}
-
-func (f *frontendCLI) processAPIError(err error) {
- log.Warn("API error: ", err)
- switch err {
- case pmapi.ErrNoConnection:
- f.notifyInternetOff()
- case pmapi.ErrUpgradeApplication:
- f.notifyNeedUpgrade()
- default:
- f.Println("Server error:", err.Error())
- }
-}
-
-func (f *frontendCLI) notifyInternetOff() {
- f.Println("Internet connection is not available.")
-}
-
-func (f *frontendCLI) notifyInternetOn() {
- f.Println("Internet connection is available again.")
-}
-
-func (f *frontendCLI) notifyLogout(address string) {
- f.Printf("Account %s is disconnected. Login to continue using this account with email client.", address)
-}
-
-func (f *frontendCLI) notifyNeedUpgrade() {
- version, err := f.updater.Check()
- if err != nil {
- log.WithError(err).Error("Failed to notify need upgrade")
- return
- }
- f.Println("Please download and install the newest version of application from", version.LandingPage)
-}
-
-func (f *frontendCLI) notifyCredentialsError() { // nolint[unused]
- // Print in 80-column width.
- f.Println("ProtonMail Import-Export app is not able to detect a supported password manager")
- f.Println("(pass, gnome-keyring). Please install and set up a supported password manager")
- f.Println("and restart the application.")
-}
-
-func (f *frontendCLI) notifyCertIssue() {
- // Print in 80-column width.
- f.Println(`Connection security error: Your network connection to Proton services may
-be insecure.
-
-Description:
-ProtonMail Import-Export was not able to establish a secure connection to Proton
-servers due to a TLS certificate error. This means your connection may
-potentially be insecure and susceptible to monitoring by third parties.
-
-Recommendation:
-* If you trust your network operator, you can continue to use ProtonMail
- as usual.
-* If you don't trust your network operator, reconnect to ProtonMail over a VPN
- (such as ProtonVPN) which encrypts your Internet connection, or use
- a different network to access ProtonMail.
-`)
-}
diff --git a/internal/frontend/frontend.go b/internal/frontend/frontend.go
index 0335d91c..4f7ad05a 100644
--- a/internal/frontend/frontend.go
+++ b/internal/frontend/frontend.go
@@ -24,22 +24,12 @@ import (
"github.com/ProtonMail/proton-bridge/internal/config/settings"
"github.com/ProtonMail/proton-bridge/internal/config/useragent"
"github.com/ProtonMail/proton-bridge/internal/frontend/cli"
- cliie "github.com/ProtonMail/proton-bridge/internal/frontend/cli-ie"
- "github.com/ProtonMail/proton-bridge/internal/frontend/qt"
- qtie "github.com/ProtonMail/proton-bridge/internal/frontend/qt-ie"
"github.com/ProtonMail/proton-bridge/internal/frontend/types"
- "github.com/ProtonMail/proton-bridge/internal/importexport"
"github.com/ProtonMail/proton-bridge/internal/locations"
"github.com/ProtonMail/proton-bridge/internal/updater"
"github.com/ProtonMail/proton-bridge/pkg/listener"
- "github.com/sirupsen/logrus"
)
-var (
- log = logrus.WithField("pkg", "frontend") // nolint[unused]
-)
-
-// Frontend is an interface to be implemented by each frontend type (cli, gui, html).
type Frontend interface {
Loop() error
NotifyManualUpdate(update updater.VersionInfo, canInstall bool)
@@ -68,42 +58,6 @@ func New(
restarter types.Restarter,
) Frontend {
bridgeWrap := types.NewBridgeWrap(bridge)
- return newBridgeFrontend(
- version,
- buildVersion,
- programName,
- frontendType,
- showWindowOnStart,
- panicHandler,
- locations,
- settings,
- eventListener,
- updater,
- userAgent,
- bridgeWrap,
- noEncConfirmator,
- autostart,
- restarter,
- )
-}
-
-func newBridgeFrontend(
- version,
- buildVersion,
- programName,
- frontendType string,
- showWindowOnStart bool,
- panicHandler types.PanicHandler,
- locations *locations.Locations,
- settings *settings.Settings,
- eventListener listener.Listener,
- updater types.Updater,
- userAgent *useragent.UserAgent,
- bridge types.Bridger,
- noEncConfirmator types.NoEncConfirmator,
- autostart *autostart.App,
- restarter types.Restarter,
-) Frontend {
switch frontendType {
case "cli":
return cli.New(
@@ -112,94 +66,10 @@ func newBridgeFrontend(
settings,
eventListener,
updater,
- bridge,
+ bridgeWrap,
restarter,
)
default:
- return qt.New(
- version,
- buildVersion,
- programName,
- showWindowOnStart,
- panicHandler,
- locations,
- settings,
- eventListener,
- updater,
- userAgent,
- bridge,
- noEncConfirmator,
- autostart,
- restarter,
- )
- }
-}
-
-// NewImportExport returns initialized frontend based on `frontendType`, which can be `cli` or `qt`.
-func NewImportExport(
- version,
- buildVersion,
- programName,
- frontendType string,
- panicHandler types.PanicHandler,
- locations *locations.Locations,
- settings *settings.Settings,
- eventListener listener.Listener,
- updater types.Updater,
- ie *importexport.ImportExport,
- restarter types.Restarter,
-) Frontend {
- ieWrap := types.NewImportExportWrap(ie)
- return newIEFrontend(
- version,
- buildVersion,
- programName,
- frontendType,
- panicHandler,
- locations,
- settings,
- eventListener,
- updater,
- ieWrap,
- restarter,
- )
-}
-
-func newIEFrontend(
- version,
- buildVersion,
- programName,
- frontendType string,
- panicHandler types.PanicHandler,
- locations *locations.Locations,
- settings *settings.Settings,
- eventListener listener.Listener,
- updater types.Updater,
- ie types.ImportExporter,
- restarter types.Restarter,
-) Frontend {
- switch frontendType {
- case "cli":
- return cliie.New(
- panicHandler,
- locations,
- eventListener,
- updater,
- ie,
- restarter,
- )
- default:
- return qtie.New(
- version,
- buildVersion,
- programName,
- panicHandler,
- locations,
- settings,
- eventListener,
- updater,
- ie,
- restarter,
- )
+ return nil
}
}
diff --git a/internal/frontend/qml/BridgeUI/AccountDelegate.qml b/internal/frontend/qml/BridgeUI/AccountDelegate.qml
deleted file mode 100644
index 1369e365..00000000
--- a/internal/frontend/qml/BridgeUI/AccountDelegate.qml
+++ /dev/null
@@ -1,430 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-import QtQuick 2.8
-import ProtonUI 1.0
-import BridgeUI 1.0
-
-// NOTE: Keep the Column so the height and width is inherited from content
-Column {
- id: root
- state: status
- anchors.left: parent.left
-
- property int row_width: 50 * Style.px
- property int row_height: Style.accounts.heightAccount
- property var listalias : aliases.split(";")
- property int iAccount: index
-
- Accessible.role: go.goos=="windows" ? Accessible.Grouping : Accessible.Row
- Accessible.name: qsTr("Account %1, status %2", "Accessible text describing account row with arguments: account name and status (connected/disconnected), resp.").arg(account).arg(statusMark.text)
- Accessible.description: Accessible.name
- Accessible.ignored: !enabled || !visible
-
- // Main row
- Rectangle {
- id: mainaccRow
- anchors.left: parent.left
- width : row_width
- height : row_height
- state: { return isExpanded ? "expanded" : "collapsed" }
- color: Style.main.background
-
- property string actionName : (
- isExpanded ?
- qsTr("Collapse row for account %2", "Accessible text of button showing additional configuration of account") :
- qsTr("Expand row for account %2", "Accessible text of button hiding additional configuration of account")
- ). arg(account)
-
-
- // override by other buttons
- MouseArea {
- id: mouseArea
- anchors.fill: parent
- onClicked : {
- if (root.state=="connected") {
- mainaccRow.toggle_accountSettings()
- }
- }
- cursorShape : root.state == "connected" ? Qt.PointingHandCursor : Qt.ArrowCursor
- hoverEnabled: true
- onEntered: {
- if (mainaccRow.state=="collapsed") {
- mainaccRow.color = Qt.lighter(Style.main.background,1.1)
- }
- }
- onExited: {
- if (mainaccRow.state=="collapsed") {
- mainaccRow.color = Style.main.background
- }
- }
- }
-
- // toggle down/up icon
- Text {
- id: toggleIcon
- anchors {
- left : parent.left
- verticalCenter : parent.verticalCenter
- leftMargin : Style.main.leftMargin
- }
- color: Style.main.text
- font {
- pointSize : Style.accounts.sizeChevron * Style.pt
- family : Style.fontawesome.name
- }
- text: Style.fa.chevron_down
-
- MouseArea {
- anchors.fill: parent
- Accessible.role: Accessible.Button
- Accessible.name: mainaccRow.actionName
- Accessible.description: mainaccRow.actionName
- Accessible.onPressAction : mainaccRow.toggle_accountSettings()
- Accessible.ignored: root.state!="connected" || !root.enabled
- }
- }
-
- // account name
- TextMetrics {
- id: accountMetrics
- font : accountName.font
- elide: Qt.ElideMiddle
- elideWidth: Style.accounts.elideWidth
- text: account
- }
- Text {
- id: accountName
- anchors {
- verticalCenter : parent.verticalCenter
- left : toggleIcon.left
- leftMargin : Style.main.leftMargin
- }
- color: Style.main.text
- font {
- pointSize : (Style.main.fontSize+2*Style.px) * Style.pt
- }
- text: accountMetrics.elidedText
- }
-
- // status
- ClickIconText {
- id: statusMark
- anchors {
- verticalCenter : parent.verticalCenter
- left : parent.left
- leftMargin : Style.accounts.leftMargin2
- }
- text : qsTr("connected", "status of a listed logged-in account")
- iconText : Style.fa.circle_o
- textColor : Style.main.textGreen
- enabled : false
- Accessible.ignored: true
- }
-
- // logout
- ClickIconText {
- id: logoutAccount
- anchors {
- verticalCenter : parent.verticalCenter
- left : parent.left
- leftMargin : Style.accounts.leftMargin3
- }
- text : qsTr("Log out", "action to log out a connected account")
- iconText : Style.fa.power_off
- textBold : true
- textColor : Style.main.textBlue
- }
-
- // remove
- ClickIconText {
- id: deleteAccount
- anchors {
- verticalCenter : parent.verticalCenter
- right : parent.right
- rightMargin : Style.main.rightMargin
- }
- text : qsTr("Remove", "deletes an account from the account settings page")
- iconText : Style.fa.trash_o
- textColor : Style.main.text
- onClicked : {
- dialogGlobal.input=root.iAccount
- dialogGlobal.state="deleteUser"
- dialogGlobal.show()
- }
- }
-
-
- // functions
- function toggle_accountSettings() {
- if (root.state=="connected") {
- if (mainaccRow.state=="collapsed" ) {
- mainaccRow.state="expanded"
- } else {
- mainaccRow.state="collapsed"
- }
- }
- }
-
- states: [
- State {
- name: "collapsed"
- PropertyChanges { target : toggleIcon ; text : root.state=="connected" ? Style.fa.chevron_down : " " }
- PropertyChanges { target : accountName ; font.bold : false }
- PropertyChanges { target : mainaccRow ; color : Style.main.background }
- PropertyChanges { target : addressList ; visible : false }
- },
- State {
- name: "expanded"
- PropertyChanges { target : toggleIcon ; text : Style.fa.chevron_up }
- PropertyChanges { target : accountName ; font.bold : true }
- PropertyChanges { target : mainaccRow ; color : Style.accounts.backgroundExpanded }
- PropertyChanges { target : addressList ; visible : true }
- }
- ]
- }
-
- // List of adresses
- Column {
- id: addressList
- anchors.left : parent.left
- width: row_width
- visible: false
- property alias model : repeaterAddresses.model
-
- Rectangle {
- id: addressModeWrapper
- anchors {
- left : parent.left
- right : parent.right
- }
- visible : mainaccRow.state=="expanded"
- height : 2*Style.accounts.heightAddrRow/3
- color : Style.accounts.backgroundExpanded
-
- ClickIconText {
- id: addressModeSwitch
- anchors {
- top : addressModeWrapper.top
- right : addressModeWrapper.right
- rightMargin : Style.main.rightMargin
- }
- textColor : Style.main.textBlue
- iconText : Style.fa.exchange
- iconOnRight : false
- text : isCombinedAddressMode ?
- qsTr("Switch to split addresses mode", "Text of button switching to mode with one configuration per each address.") :
- qsTr("Switch to combined addresses mode", "Text of button switching to mode with one configuration for all addresses.")
-
- onClicked: {
- dialogGlobal.input=root.iAccount
- dialogGlobal.state="addressmode"
- dialogGlobal.show()
- }
- }
-
- ClickIconText {
- id: combinedAddressConfig
- anchors {
- top : addressModeWrapper.top
- left : addressModeWrapper.left
- leftMargin : Style.accounts.leftMarginAddr+Style.main.leftMargin
- }
- visible : isCombinedAddressMode
- text : qsTr("Mailbox configuration", "Displays IMAP/SMTP settings information for a given account")
- iconText : Style.fa.gear
- textColor : Style.main.textBlue
- onClicked : {
- infoWin.showInfo(root.iAccount,0)
- }
- }
- }
-
- Repeater {
- id: repeaterAddresses
- model: ["one", "two"]
-
- Rectangle {
- id: addressRow
- visible: !isCombinedAddressMode
- anchors {
- left : parent.left
- right : parent.right
- }
- height: Style.accounts.heightAddrRow
- color: Style.accounts.backgroundExpanded
-
- // icon level down
- Text {
- id: levelDown
- anchors {
- left : parent.left
- leftMargin : Style.accounts.leftMarginAddr
- verticalCenter : wrapAddr.verticalCenter
- }
- text : Style.fa.level_up
- font.family : Style.fontawesome.name
- color : Style.main.textDisabled
- rotation : 90
- }
-
- Rectangle {
- id: wrapAddr
- anchors {
- top : parent.top
- left : levelDown.right
- right : parent.right
- leftMargin : Style.main.leftMargin
- rightMargin : Style.main.rightMargin
- }
- height: Style.accounts.heightAddr
- border {
- width : Style.main.border
- color : Style.main.line
- }
- color: Style.accounts.backgroundAddrRow
-
- TextMetrics {
- id: addressMetrics
- font: address.font
- elideWidth: 2*wrapAddr.width/3
- elide: Qt.ElideMiddle
- text: modelData
- }
-
- Text {
- id: address
- anchors {
- verticalCenter : parent.verticalCenter
- left: parent.left
- leftMargin: Style.main.leftMargin
- }
- font.pointSize : Style.main.fontSize * Style.pt
- color: Style.main.text
- text: addressMetrics.elidedText
- }
-
- ClickIconText {
- id: addressConfig
- anchors {
- verticalCenter : parent.verticalCenter
- right: parent.right
- rightMargin: Style.main.rightMargin
- }
- text : qsTr("Address configuration", "Display the IMAP/SMTP configuration for address")
- iconText : Style.fa.gear
- textColor : Style.main.textBlue
- onClicked : infoWin.showInfo(root.iAccount,index)
-
- Accessible.description: qsTr("Address configuration for %1", "Accessible text of button displaying the IMAP/SMTP configuration for address %1").arg(modelData)
- Accessible.ignored: !enabled
- }
-
- MouseArea {
- id: clickSettings
- anchors.fill: wrapAddr
- onClicked : addressConfig.clicked()
- cursorShape: Qt.PointingHandCursor
- hoverEnabled: true
- onPressed: {
- wrapAddr.color = Qt.rgba(1,1,1,0.20)
- }
- onEntered: {
- wrapAddr.color = Qt.rgba(1,1,1,0.15)
- }
- onExited: {
- wrapAddr.color = Style.accounts.backgroundAddrRow
- }
- }
- }
- }
- }
- }
-
- Rectangle {
- id: line
- color: Style.accounts.line
- height: Style.accounts.heightLine
- width: root.row_width
- }
-
-
- states: [
- State {
- name: "connected"
- PropertyChanges {
- target : addressList
- model : listalias
- }
- PropertyChanges {
- target : toggleIcon
- color : Style.main.text
- }
- PropertyChanges {
- target : accountName
- color : Style.main.text
- }
- PropertyChanges {
- target : statusMark
- textColor : Style.main.textGreen
- text : qsTr("connected", "status of a listed logged-in account")
- iconText : Style.fa.circle
- }
- PropertyChanges {
- target : logoutAccount
- text : qsTr("Log out", "action to log out a connected account")
- onClicked : {
- mainaccRow.state="collapsed"
- dialogGlobal.input = root.iAccount
- dialogGlobal.state = "logout"
- dialogGlobal.show()
- dialogGlobal.confirmed()
- }
- }
- },
- State {
- name: "disconnected"
- PropertyChanges {
- target : addressList
- model : 0
- }
- PropertyChanges {
- target : toggleIcon
- color : Style.main.textDisabled
- }
- PropertyChanges {
- target : accountName
- color : Style.main.textDisabled
- }
- PropertyChanges {
- target : statusMark
- textColor : Style.main.textDisabled
- text : qsTr("disconnected", "status of a listed logged-out account")
- iconText : Style.fa.circle_o
- }
- PropertyChanges {
- target : logoutAccount
- text : qsTr("Log in", "action to log in a disconnected account")
- onClicked : {
- dialogAddUser.username = root.listalias[0]
- dialogAddUser.show()
- dialogAddUser.inputPassword.focusInput = true
- }
- }
- }
- ]
-}
diff --git a/internal/frontend/qml/BridgeUI/BubbleMenu.qml b/internal/frontend/qml/BridgeUI/BubbleMenu.qml
deleted file mode 100644
index 419957f4..00000000
--- a/internal/frontend/qml/BridgeUI/BubbleMenu.qml
+++ /dev/null
@@ -1,72 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// Dialog with main menu
-
-import QtQuick 2.8
-import BridgeUI 1.0
-import ProtonUI 1.0
-
-Rectangle {
- id: root
- color: "#aaff5577"
- anchors {
- left : tabbar.left
- right : tabbar.right
- top : tabbar.bottom
- bottom : parent.bottom
- }
- visible: false
-
- MouseArea {
- anchors.fill: parent
- onClicked: toggle()
- }
-
- Rectangle {
- color : Style.menu.background
- radius : Style.menu.radius
- width : Style.menu.width
- height : Style.menu.height
- anchors {
- top : parent.top
- right : parent.right
- topMargin : Style.menu.topMargin
- rightMargin : Style.menu.rightMargin
- }
-
- MouseArea {
- anchors.fill: parent
- }
-
- Text {
- anchors.centerIn: parent
- text: qsTr("About")
- color: Style.menu.text
- }
- }
-
- function toggle(){
- if (root.visible == false) {
- root.visible = true
- } else {
- root.visible = false
- }
- }
-}
-
-
diff --git a/internal/frontend/qml/BridgeUI/Credits.qml b/internal/frontend/qml/BridgeUI/Credits.qml
deleted file mode 100644
index 424b8667..00000000
--- a/internal/frontend/qml/BridgeUI/Credits.qml
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-import QtQuick 2.8
-import BridgeUI 1.0
-import ProtonUI 1.0
-
-Item {
- Rectangle {
- anchors.centerIn: parent
- width: Style.main.width
- height: 3*Style.main.height/4
- color: "transparent"
- //color: "red"
-
- ListView {
- anchors.fill: parent
- clip : true
- model : go.credits.split(";")
-
- delegate: AccessibleText {
- anchors.horizontalCenter: parent.horizontalCenter
- text: modelData
- color: Style.main.text
- font.pointSize : Style.main.fontSize * Style.pt
- }
-
- footer: ButtonRounded {
- anchors.horizontalCenter: parent.horizontalCenter
- text: qsTr("Close", "close window")
- onClicked: dialogCredits.hide()
- }
- }
- }
-}
diff --git a/internal/frontend/qml/BridgeUI/DialogFirstStart.qml b/internal/frontend/qml/BridgeUI/DialogFirstStart.qml
deleted file mode 100644
index a3488f4f..00000000
--- a/internal/frontend/qml/BridgeUI/DialogFirstStart.qml
+++ /dev/null
@@ -1,124 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// Dialog with Yes/No buttons
-
-import QtQuick 2.8
-import ProtonUI 1.0
-
-Dialog {
- id: root
-
- title : ""
- isDialogBusy: false
- property string firstParagraph : qsTr("The Bridge is an application that runs on your computer in the background and seamlessly encrypts and decrypts your mail as it enters and leaves your computer.", "instructions that appear on welcome screen at first start")
- property string secondParagraph : qsTr("To add your ProtonMail account to the Bridge and generate your Bridge password, please see the installation guide for detailed setup instructions.", "confirms and dismisses a notification (URL that leads to installation guide should stay intact)")
-
- Column {
- id: dialogMessage
- property int heightInputs : welcome.height + middleSep.height + instructions.height + buttSep.height + buttonOkay.height + imageSep.height + logo.height
-
- Rectangle { color : "transparent"; width : Style.main.dummy; height : (root.height-dialogMessage.heightInputs)/2 }
-
- Text {
- id:welcome
- color: Style.main.text
- font.bold: true
- font.pointSize: 1.5*Style.main.fontSize*Style.pt
- anchors.horizontalCenter: parent.horizontalCenter
- horizontalAlignment: Text.AlignHCenter
- text: qsTr("Welcome to the", "welcome screen that appears on first start")
- }
-
- Rectangle {id: imageSep; color : "transparent"; width : Style.main.dummy; height : Style.dialog.heightSeparator }
-
-
- Row {
- anchors.horizontalCenter: parent.horizontalCenter
- spacing: Style.dialog.spacing
- Image {
- id: logo
- anchors.bottom : pmbridge.baseline
- height : 2*Style.main.fontSize
- fillMode : Image.PreserveAspectFit
- mipmap : true
- source : "../ProtonUI/images/pm_logo.png"
- }
- AccessibleText {
- id:pmbridge
- color: Style.main.text
- font.bold: true
- font.pointSize: 2.2*Style.main.fontSize*Style.pt
- horizontalAlignment: Text.AlignHCenter
- text: qsTr("ProtonMail Bridge", "app title")
-
- Accessible.name: this.clearText(pmbridge.text)
- Accessible.description: this.clearText(welcome.text+ " " + pmbridge.text + ". " + root.firstParagraph + ". " + root.secondParagraph)
- }
- }
-
-
-
- Rectangle { id:middleSep; color : "transparent"; width : Style.main.dummy; height : Style.dialog.heightSeparator }
-
-
- Text {
- id:instructions
- color: Style.main.text
- font.pointSize: Style.main.fontSize*Style.pt
- anchors.horizontalCenter: parent.horizontalCenter
- horizontalAlignment: Text.AlignHCenter
- width: root.width/1.5
- wrapMode: Text.Wrap
- textFormat: Text.RichText
- text: "
"+
- root.firstParagraph +
- "
"+
- root.secondParagraph +
- ""
- onLinkActivated: {
- Qt.openUrlExternally(link)
- }
- }
-
- Rectangle { id:buttSep; color : "transparent"; width : Style.main.dummy; height : 2*Style.dialog.heightSeparator }
-
-
- ButtonRounded {
- id:buttonOkay
- color_main: Style.dialog.text
- color_minor: Style.main.textBlue
- isOpaque: true
- fa_icon: Style.fa.check
- text: qsTr("Okay", "confirms and dismisses a notification")
- onClicked : root.hide()
- anchors.horizontalCenter: parent.horizontalCenter
- }
- }
-
- timer.interval : 3000
-
- Connections {
- target: timer
- onTriggered: {
- }
- }
-
- onShow : {
- pmbridge.Accessible.selected = true
- }
-}
diff --git a/internal/frontend/qml/BridgeUI/DialogKeychainChange.qml b/internal/frontend/qml/BridgeUI/DialogKeychainChange.qml
deleted file mode 100644
index 7664214a..00000000
--- a/internal/frontend/qml/BridgeUI/DialogKeychainChange.qml
+++ /dev/null
@@ -1,194 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// Change default keychain dialog
-
-import QtQuick 2.8
-import BridgeUI 1.0
-import ProtonUI 1.0
-import QtQuick.Controls 2.2 as QC
-import QtQuick.Layouts 1.0
-
-Dialog {
- id: root
-
- title : "Change which keychain Bridge uses as default"
- subtitle : "Select which keychain is used (Bridge will automatically restart)"
- isDialogBusy: currentIndex==1
-
- property var selectedKeychain
-
- Connections {
- target: go.selectedKeychain
- onValueChanged: {
- console.debug("go.selectedKeychain == ", go.selectedKeychain)
- }
- }
-
- ColumnLayout {
- Layout.fillHeight: true
- Layout.fillWidth: true
-
- Item {
- Layout.fillWidth: true
- Layout.minimumHeight: root.titleHeight + Style.dialog.heightSeparator
- Layout.maximumHeight: root.titleHeight + Style.dialog.heightSeparator
- }
-
- Item {
- Layout.fillHeight: true
- Layout.fillWidth: true
-
- ColumnLayout {
- anchors.centerIn: parent
-
- Repeater {
- id: keychainRadioButtons
- model: go.availableKeychain
- QC.RadioButton {
- id: radioDelegate
- text: modelData
- checked: go.selectedKeychain === modelData
-
- Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
- spacing: Style.main.spacing
-
- indicator: Text {
- text : radioDelegate.checked ? Style.fa.check_circle : Style.fa.circle_o
- color : radioDelegate.checked ? Style.main.textBlue : Style.main.textInactive
- font {
- pointSize: Style.dialog.iconSize * Style.pt
- family: Style.fontawesome.name
- }
- }
- contentItem: Text {
- text: radioDelegate.text
- color: Style.main.text
- font {
- pointSize: Style.dialog.fontSize * Style.pt
- bold: checked
- }
- horizontalAlignment : Text.AlignHCenter
- verticalAlignment : Text.AlignVCenter
- leftPadding: Style.dialog.iconSize
- }
-
- onCheckedChanged: {
- if (checked) {
- root.selectedKeychain = modelData
- }
- }
- }
- }
-
- Item {
- Layout.fillWidth: true
- Layout.minimumHeight: Style.dialog.heightSeparator
- Layout.maximumHeight: Style.dialog.heightSeparator
- }
-
- Row {
- id: buttonRow
- Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
- spacing: Style.dialog.spacing
- ButtonRounded {
- id:buttonNo
- color_main: Style.dialog.text
- fa_icon: Style.fa.times
- text: qsTr("Cancel", "dismisses current action")
- onClicked : root.hide()
- }
- ButtonRounded {
- id: buttonYes
- color_main: Style.dialog.text
- color_minor: Style.main.textBlue
- isOpaque: true
- fa_icon: Style.fa.check
- text: qsTr("Okay", "confirms and dismisses a notification")
- onClicked : root.confirmed()
- }
- }
- }
- }
- }
-
- ColumnLayout {
- Layout.fillHeight: true
- Layout.fillWidth: true
-
- Item {
- Layout.fillWidth: true
- Layout.minimumHeight: root.titleHeight + Style.dialog.heightSeparator
- Layout.maximumHeight: root.titleHeight + Style.dialog.heightSeparator
- }
-
- Item {
- Layout.fillHeight: true
- Layout.fillWidth: true
- Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
-
- Text {
- id: answ
- anchors.horizontalCenter: parent.horizontalCenter
- anchors.verticalCenter: parent.verticalCenter
- width : parent.width/2
- color: Style.dialog.text
- font {
- pointSize : Style.dialog.fontSize * Style.pt
- bold : true
- }
- text : "Default keychain is now set to " + root.selectedKeychain +
- "\n\n" +
- qsTr("Settings will be applied after the next start.", "notification about setting being applied after next start") +
- "\n\n" +
- qsTr("Bridge will now restart.", "notification about restarting")
- wrapMode: Text.Wrap
- horizontalAlignment: Text.AlignHCenter
- }
- }
- }
-
- Shortcut {
- sequence: StandardKey.Cancel
- onActivated: root.hide()
- }
-
- Shortcut {
- sequence: "Enter"
- onActivated: root.confirmed()
- }
-
- function confirmed() {
- if (selectedKeychain === go.selectedKeychain) {
- root.hide()
- return
- }
-
- incrementCurrentIndex()
- timer.start()
- }
-
- timer.interval : 5000
-
- Connections {
- target: timer
- onTriggered: {
- // This action triggers restart on the backend side.
- go.selectedKeychain = selectedKeychain
- }
- }
-}
diff --git a/internal/frontend/qml/BridgeUI/DialogPortChange.qml b/internal/frontend/qml/BridgeUI/DialogPortChange.qml
deleted file mode 100644
index 078be9f8..00000000
--- a/internal/frontend/qml/BridgeUI/DialogPortChange.qml
+++ /dev/null
@@ -1,233 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// Dialog with Yes/No buttons
-
-import QtQuick 2.8
-import BridgeUI 1.0
-import ProtonUI 1.0
-import QtQuick.Controls 2.2 as QC
-
-Dialog {
- id: root
-
- title : "Set IMAP & SMTP settings"
- subtitle : "Changes require reconfiguration of Mail client. (Bridge will automatically restart)"
- isDialogBusy: currentIndex==1
-
- Column {
- id: dialogMessage
- property int heightInputs : imapPort.height + middleSep.height + smtpPort.height + buttonSep.height + buttonRow.height + secSMTPSep.height + securitySMTP.height
-
- Rectangle { color : "transparent"; width : Style.main.dummy; height : (root.height-dialogMessage.heightInputs)/1.6 }
-
- InputField {
- id: imapPort
- iconText : Style.fa.hashtag
- label : qsTr("IMAP port", "entry field to choose port used for the IMAP server")
- text : "undef"
- }
-
- Rectangle { id:middleSep; color : "transparent"; width : Style.main.dummy; height : Style.dialog.heightSeparator }
-
- InputField {
- id: smtpPort
- iconText : Style.fa.hashtag
- label : qsTr("SMTP port", "entry field to choose port used for the SMTP server")
- text : "undef"
- }
-
- Rectangle { id:secSMTPSep; color : Style.transparent; width : Style.main.dummy; height : Style.dialog.heightSeparator }
-
- // SSL button group
- Rectangle {
- anchors.horizontalCenter : parent.horizontalCenter
- width : Style.dialog.widthInput
- height : securitySMTPLabel.height + securitySMTP.height
- color : "transparent"
-
- AccessibleText {
- id: securitySMTPLabel
- anchors.left : parent.left
- text:qsTr("SMTP connection mode")
- color: Style.dialog.text
- font {
- pointSize : Style.dialog.fontSize * Style.pt
- bold : true
- }
- }
-
- QC.ButtonGroup {
- buttons: securitySMTP.children
- }
- Row {
- id: securitySMTP
- spacing: Style.dialog.spacing
- anchors.top: securitySMTPLabel.bottom
- anchors.topMargin: Style.dialog.fontSize
-
- CheckBoxLabel {
- id: securitySMTPSSL
- text: qsTr("SSL")
- }
-
- CheckBoxLabel {
- checked: true
- id: securitySMTPSTARTTLS
- text: qsTr("STARTTLS")
- }
- }
- }
-
- Rectangle { id:buttonSep; color : "transparent"; width : Style.main.dummy; height : 2*Style.dialog.heightSeparator }
-
- Row {
- id: buttonRow
- anchors.horizontalCenter: parent.horizontalCenter
- spacing: Style.dialog.spacing
- ButtonRounded {
- id:buttonNo
- color_main: Style.dialog.text
- fa_icon: Style.fa.times
- text: qsTr("Cancel", "dismisses current action")
- onClicked : root.hide()
- }
- ButtonRounded {
- id: buttonYes
- color_main: Style.dialog.text
- color_minor: Style.main.textBlue
- isOpaque: true
- fa_icon: Style.fa.check
- text: qsTr("Okay", "confirms and dismisses a notification")
- onClicked : root.confirmed()
- }
- }
- }
-
- Column {
- Rectangle { color : "transparent"; width : Style.main.dummy; height : (root.height-answ.height)/2 }
- Text {
- id: answ
- anchors.horizontalCenter: parent.horizontalCenter
- width : parent.width/2
- color: Style.dialog.text
- font {
- pointSize : Style.dialog.fontSize * Style.pt
- bold : true
- }
- text : "IMAP: " + imapPort.text + "\nSMTP: " + smtpPort.text + "\nSMTP Connection Mode: " + getSelectedSSLMode() + "\n\n" +
- qsTr("Settings will be applied after the next start. You will need to reconfigure your email client(s).", "after user changes their ports they will see this notification to reconfigure their setup") +
- "\n\n" +
- qsTr("Bridge will now restart.", "after user changes their ports this appears to notify the user of restart")
- wrapMode: Text.Wrap
- horizontalAlignment: Text.AlignHCenter
- }
- }
-
- function areInputsOK() {
- var isOK = true
- var imapUnchanged = false
- var secSMTPUnchanged = (securitySMTPSTARTTLS.checked == go.isSMTPSTARTTLS())
- root.warning.text = ""
-
- if (imapPort.text!=go.getIMAPPort()) {
- if (go.isPortOpen(imapPort.text)!=0) {
- imapPort.rightIcon = Style.fa.exclamation_triangle
- root.warning.text = qsTr("Port number is not available.", "if the user changes one of their ports to a port that is occupied by another application")
- isOK=false
- } else {
- imapPort.rightIcon = Style.fa.check_circle
- }
- } else {
- imapPort.rightIcon = ""
- imapUnchanged = true
- }
-
- if (smtpPort.text!=go.getSMTPPort()) {
- if (go.isPortOpen(smtpPort.text)!=0) {
- smtpPort.rightIcon = Style.fa.exclamation_triangle
- root.warning.text = qsTr("Port number is not available.", "if the user changes one of their ports to a port that is occupied by another application")
- isOK=false
- } else {
- smtpPort.rightIcon = Style.fa.check_circle
- }
- } else {
- smtpPort.rightIcon = ""
- if (imapUnchanged && secSMTPUnchanged) {
- root.warning.text = qsTr("Please change at least one port number or SMTP security.", "if the user tries to change IMAP/SMTP ports to the same ports as before")
- isOK=false
- }
- }
-
- if (imapPort.text == smtpPort.text) {
- smtpPort.rightIcon = Style.fa.exclamation_triangle
- root.warning.text = qsTr("Port numbers must be different.", "if the user sets both the IMAP and SMTP ports to the same number")
- isOK=false
- }
-
- root.warning.visible = !isOK
- return isOK
- }
-
- function confirmed() {
- if (areInputsOK()) {
- incrementCurrentIndex()
- timer.start()
- }
- }
-
- function getSelectedSSLMode() {
- if (securitySMTPSTARTTLS.checked == true) {
- return "STARTTLS"
- } else {
- return "SSL"
- }
- }
-
- onShow : {
- imapPort.text = go.getIMAPPort()
- smtpPort.text = go.getSMTPPort()
- if (go.isSMTPSTARTTLS()) {
- securitySMTPSTARTTLS.checked = true
- } else {
- securitySMTPSSL.checked = true
- }
- areInputsOK()
- root.warning.visible = false
- }
-
- Shortcut {
- sequence: StandardKey.Cancel
- onActivated: root.hide()
- }
-
- Shortcut {
- sequence: "Enter"
- onActivated: root.confirmed()
- }
-
- timer.interval : 3000
-
- Connections {
- target: timer
- onTriggered: {
- go.setPortsAndSecurity(imapPort.text, smtpPort.text, securitySMTPSTARTTLS.checked)
- go.setToRestart()
- Qt.quit()
- }
- }
-}
diff --git a/internal/frontend/qml/BridgeUI/DialogTLSCertInfo.qml b/internal/frontend/qml/BridgeUI/DialogTLSCertInfo.qml
deleted file mode 100644
index 986d817c..00000000
--- a/internal/frontend/qml/BridgeUI/DialogTLSCertInfo.qml
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-import QtQuick 2.8
-import BridgeUI 1.0
-import ProtonUI 1.0
-
-
-Dialog {
- id: root
- title: qsTr("Connection security error", "Title of modal explainning TLS issue")
-
- property string par1Title : qsTr("Description:", "Title of paragraph describing the issue")
- property string par1Text : qsTr (
- "ProtonMail Bridge was not able to establish a secure connection to Proton servers due to a TLS certificate error. "+
- "This means your connection may potentially be insecure and susceptible to monitoring by third parties.",
- "A paragraph describing the issue"
- )
-
- property string par2Title : qsTr("Recommendation:", "Title of paragraph describing recommended steps")
- property string par2Text : qsTr (
- "If you are on a corporate or public network, the network administrator may be monitoring or intercepting all traffic.",
- "A paragraph describing network issue"
- )
- property string par2ul1 : qsTr(
- "If you trust your network operator, you can continue to use ProtonMail as usual.",
- "A list item describing recomendation for trusted network"
- )
-
- property string par2ul2 : qsTr(
- "If you don't trust your network operator, reconnect to ProtonMail over a VPN (such as ProtonVPN) "+
- "which encrypts your Internet connection, or use a different network to access ProtonMail.",
- "A list item describing recomendation for untrusted network"
- )
- property string par3Text : qsTr("Learn more on our knowledge base article","A paragraph describing where to find more information")
- property string kbArticleText : qsTr("What is TLS certificate error.", "Link text for knowledge base article")
- property string kbArticleLink : "https://protonmail.com/support/knowledge-base/"
-
-
- Item {
- AccessibleText {
- anchors.centerIn: parent
- color: Style.old.pm_white
- linkColor: color
- width: parent.width - 50 * Style.px
- wrapMode: Text.WordWrap
- font.pointSize: Style.main.fontSize*Style.pt
- onLinkActivated: Qt.openUrlExternally(link)
- text: ""+par1Title+"
"+
- par1Text+"
\n"+
- ""+par2Title+"
"+
- par2Text+
- ""+
- "- "+par2ul1+"
"+
- "- "+par2ul2+"
"+
- "
"+"
\n"+
- ""
- //par3Text+
- //" "+kbArticleText+"\n"
- }
- }
-}
-
diff --git a/internal/frontend/qml/BridgeUI/DialogYesNo.qml b/internal/frontend/qml/BridgeUI/DialogYesNo.qml
deleted file mode 100644
index e5392f60..00000000
--- a/internal/frontend/qml/BridgeUI/DialogYesNo.qml
+++ /dev/null
@@ -1,403 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// Dialog with Yes/No buttons
-
-import QtQuick 2.8
-import BridgeUI 1.0
-import ProtonUI 1.0
-
-Dialog {
- id: root
-
- title : ""
-
- property string input
-
- property alias question : msg.text
- property alias note : noteText.text
- property alias answer : answ.text
- property alias buttonYes : buttonYes
- property alias buttonNo : buttonNo
-
- isDialogBusy: currentIndex==1
-
- signal confirmed()
-
- Column {
- id: dialogMessage
- property int heightInputs : msg.height+
- middleSep.height+
- buttonRow.height +
- (checkboxSep.visible ? checkboxSep.height : 0 ) +
- (noteSep.visible ? noteSep.height : 0 ) +
- (checkBoxWrapper.visible ? checkBoxWrapper.height : 0 ) +
- (root.note!="" ? noteText.height : 0 )
-
- Rectangle { color : "transparent"; width : Style.main.dummy; height : (root.height-dialogMessage.heightInputs)/2 }
-
- AccessibleText {
- id:noteText
- anchors.horizontalCenter: parent.horizontalCenter
- color: Style.dialog.text
- font {
- pointSize: Style.dialog.fontSize * Style.pt
- bold: false
- }
- width: 2*root.width/3
- horizontalAlignment: Text.AlignHCenter
- wrapMode: Text.Wrap
- }
- Rectangle { id: noteSep; visible: note!=""; color : "transparent"; width : Style.main.dummy; height : Style.dialog.heightSeparator}
-
- AccessibleText {
- id: msg
- anchors.horizontalCenter: parent.horizontalCenter
- color: Style.dialog.text
- font {
- pointSize: Style.dialog.fontSize * Style.pt
- bold: true
- }
- width: 2*parent.width/3
- text : ""
- horizontalAlignment: Text.AlignHCenter
- wrapMode: Text.Wrap
- }
-
- Rectangle { id: checkboxSep; visible: checkBoxWrapper.visible; color : "transparent"; width : Style.main.dummy; height : Style.dialog.heightSeparator}
- Row {
- id: checkBoxWrapper
- property bool isChecked : false
- visible: root.state=="deleteUser"
- anchors.horizontalCenter: parent.horizontalCenter
- spacing: Style.dialog.spacing
-
- function toggle() {
- checkBoxWrapper.isChecked = !checkBoxWrapper.isChecked
- }
-
- Text {
- id: checkbox
- font {
- pointSize : Style.dialog.iconSize * Style.pt
- family : Style.fontawesome.name
- }
- anchors.verticalCenter : parent.verticalCenter
- text: checkBoxWrapper.isChecked ? Style.fa.check_square_o : Style.fa.square_o
- color: checkBoxWrapper.isChecked ? Style.main.textBlue : Style.main.text
-
- MouseArea {
- anchors.fill: parent
- onPressed: checkBoxWrapper.toggle()
- cursorShape: Qt.PointingHandCursor
- }
- }
- Text {
- id: checkBoxNote
- anchors.verticalCenter : parent.verticalCenter
- text: qsTr("Additionally delete all stored preferences and data", "when removing an account, this extra preference additionally deletes all cached data")
- color: Style.main.text
- font.pointSize: Style.dialog.fontSize * Style.pt
-
- MouseArea {
- anchors.fill: parent
- onPressed: checkBoxWrapper.toggle()
- cursorShape: Qt.PointingHandCursor
-
- Accessible.role: Accessible.CheckBox
- Accessible.checked: checkBoxWrapper.isChecked
- Accessible.name: checkBoxNote.text
- Accessible.description: checkBoxNote.text
- Accessible.ignored: checkBoxNote.text == ""
- Accessible.onToggleAction: checkBoxWrapper.toggle()
- Accessible.onPressAction: checkBoxWrapper.toggle()
- }
- }
- }
-
- Rectangle { id: middleSep; color : "transparent"; width : Style.main.dummy; height : 2*Style.dialog.heightSeparator }
-
- Row {
- id: buttonRow
- anchors.horizontalCenter: parent.horizontalCenter
- spacing: Style.dialog.spacing
- ButtonRounded {
- id:buttonNo
- visible: root.state != "toggleEarlyAccess"
- color_main: Style.dialog.text
- fa_icon: Style.fa.times
- text: qsTr("No")
- onClicked : root.hide()
- }
- ButtonRounded {
- id: buttonYes
- color_main: Style.dialog.text
- color_minor: Style.main.textBlue
- isOpaque: true
- fa_icon: Style.fa.check
- text: root.state == "toggleEarlyAccess" ? qsTr("Ok") : qsTr("Yes")
- onClicked : {
- currentIndex=1
- root.confirmed()
- }
- }
- }
- }
-
-
- Column {
- Rectangle { color : "transparent"; width : Style.main.dummy; height : (root.height-answ.height)/2 }
- AccessibleText {
- id: answ
- anchors.horizontalCenter: parent.horizontalCenter
- color: Style.old.pm_white
- font {
- pointSize : Style.dialog.fontSize * Style.pt
- bold : true
- }
- width: 3*parent.width/4
- horizontalAlignment: Text.AlignHCenter
- text : qsTr("Waiting...", "in general this displays between screens when processing data takes a long time")
- wrapMode: Text.Wrap
- }
- }
-
-
- states : [
- State {
- name: "quit"
- PropertyChanges {
- target: root
- currentIndex : 0
- title : qsTr("Close Bridge", "quits the application")
- question : qsTr("Are you sure you want to close the Bridge?", "asked when user tries to quit the application")
- note : ""
- answer : qsTr("Closing Bridge...", "displayed when user is quitting application")
- }
- },
- State {
- name: "logout"
- PropertyChanges {
- target: root
- currentIndex : 1
- title : qsTr("Logout", "title of page that displays during account logout")
- question : ""
- note : ""
- answer : qsTr("Logging out...", "displays during account logout")
- }
- },
- State {
- name: "deleteUser"
- PropertyChanges {
- target: root
- currentIndex : 0
- title : qsTr("Delete account", "title of page that displays during account deletion")
- question : qsTr("Are you sure you want to remove this account?", "displays during account deletion")
- note : ""
- answer : qsTr("Deleting ...", "displays during account deletion")
- }
- },
- State {
- name: "clearChain"
- PropertyChanges {
- target : root
- currentIndex : 0
- title : qsTr("Clear keychain", "title of page that displays during keychain clearing")
- question : qsTr("Are you sure you want to clear your keychain?", "displays during keychain clearing")
- note : qsTr("This will remove all accounts that you have added to the Bridge and disconnect you from your email client(s).", "displays during keychain clearing")
- answer : qsTr("Clearing the keychain ...", "displays during keychain clearing")
- }
- },
- State {
- name: "clearCache"
- PropertyChanges {
- target: root
- currentIndex : 0
- title : qsTr("Clear cache", "title of page that displays during cache clearing")
- question : qsTr("Are you sure you want to clear your local cache?", "displays during cache clearing")
- note : qsTr("This will delete all of your stored preferences as well as cached email data for all accounts, and requires you to reconfigure your client.", "displays during cache clearing")
- answer : qsTr("Clearing the cache ...", "displays during cache clearing")
- }
- },
- State {
- name: "checkUpdates"
- PropertyChanges {
- target: root
- currentIndex : 1
- title : ""
- question : ""
- note : ""
- answer : qsTr("Checking for updates ...", "displays if user clicks the Check for Updates button in the Help tab")
- }
- },
- State {
- name: "addressmode"
- PropertyChanges {
- target: root
- currentIndex : 0
- title : ""
- question : qsTr("Do you want to continue?", "asked when the user changes between split and combined address mode")
- note : qsTr("Changing between split and combined address mode will require you to delete your account(s) from your email client and begin the setup process from scratch.", "displayed when the user changes between split and combined address mode")
- answer : qsTr("Configuring address mode...", "displayed when the user changes between split and combined address mode")
- }
- },
- State {
- name: "toggleAutoStart"
- PropertyChanges {
- target: root
- currentIndex : 1
- question : ""
- note : ""
- title : ""
- answer : {
- var msgTurnOn = qsTr("Turning on automatic start of Bridge...", "when the automatic start feature is selected")
- var msgTurnOff = qsTr("Turning off automatic start of Bridge...", "when the automatic start feature is deselected")
- return go.isAutoStart==false ? msgTurnOff : msgTurnOn
- }
- }
- },
- State {
- name: "toggleAllowProxy"
- PropertyChanges {
- target: root
- currentIndex : 0
- question : {
- var questionTurnOn = qsTr("Do you want to allow alternative routing?")
- var questionTurnOff = qsTr("Do you want to disallow alternative routing?")
- return go.isProxyAllowed==false ? questionTurnOn : questionTurnOff
- }
- note : qsTr("In case Proton sites are blocked, this setting allows Bridge to try alternative network routing to reach Proton, which can be useful for bypassing firewalls or network issues. We recommend keeping this setting on for greater reliability.")
- title : {
- var titleTurnOn = qsTr("Allow alternative routing")
- var titleTurnOff = qsTr("Disallow alternative routing")
- return go.isProxyAllowed==false ? titleTurnOn : titleTurnOff
- }
- answer : {
- var msgTurnOn = qsTr("Allowing Bridge to use alternative routing to connect to Proton...", "when the allow proxy feature is selected")
- var msgTurnOff = qsTr("Disallowing Bridge to use alternative routing to connect to Proton...", "when the allow proxy feature is deselected")
- return go.isProxyAllowed==false ? msgTurnOn : msgTurnOff
- }
- }
- },
- State {
- name: "toggleEarlyAccessOn"
- PropertyChanges {
- target: root
- currentIndex : 0
- question : qsTr("Do you want to be the first to get the latest updates? Please keep in mind that early versions may be less stable.")
- note : ""
- title : qsTr("Enable early access")
- answer : qsTr("Enabling early access...")
- }
- },
- State {
- name: "toggleEarlyAccessOff"
- PropertyChanges {
- target: root
- currentIndex : 0
- question : qsTr("Are you sure you want to leave early access? Please keep in mind this operation clears the cache and restarts Bridge.")
- note : qsTr("This will delete all of your stored preferences as well as cached email data for all accounts, and requires you to reconfigure your client.")
- title : qsTr("Disable early access")
- answer : qsTr("Disabling early access...")
- }
- },
- State {
- name: "noKeychain"
- PropertyChanges {
- target: root
- currentIndex : 0
- note : qsTr(
- "%1 is not able to detected a supported password manager (pass, gnome-keyring). Please install and setup supported password manager and restart the application.",
- "Error message when no keychain is detected"
- ).arg(go.programTitle)
- question : qsTr("Do you want to close application now?", "when no password manager found." )
- title : "No system password manager detected"
- answer : qsTr("Closing Bridge...", "displayed when user is quitting application")
- }
- },
- State {
- name: "undef";
- PropertyChanges {
- target: root
- currentIndex : 1
- question : ""
- note : ""
- title : ""
- answer : ""
- }
- }
- ]
-
-
- Shortcut {
- sequence: StandardKey.Cancel
- onActivated: root.hide()
- }
-
- Shortcut {
- sequence: "Enter"
- onActivated: root.confirmed()
- }
-
- onHide: {
- checkBoxWrapper.isChecked = false
- state = "undef"
- }
-
- onShow: {
- // hide all other dialogs
- winMain.dialogAddUser .visible = false
- winMain.dialogChangePort .visible = false
- winMain.dialogCredits .visible = false
- root.visible = true
- }
-
- onConfirmed : {
- if (state == "quit" || state == "instance exists" ) {
- timer.interval = 1000
- } else {
- timer.interval = 300
- }
- answ.forceActiveFocus()
- timer.start()
- }
-
- Connections {
- target: timer
- onTriggered: {
- if ( state == "addressmode" ) { go.switchAddressMode (input) }
- if ( state == "clearChain" ) { go.clearKeychain () }
- if ( state == "clearCache" ) { go.clearCache () }
- if ( state == "deleteUser" ) { go.deleteAccount (input, checkBoxWrapper.isChecked) }
- if ( state == "logout" ) { go.logoutAccount (input) }
- if ( state == "toggleAutoStart" ) { go.toggleAutoStart () }
- if ( state == "toggleAllowProxy" ) { go.toggleAllowProxy () }
- if ( state == "toggleEarlyAccessOn" ) { go.toggleEarlyAccess () }
- if ( state == "toggleEarlyAccessOff" ) { go.toggleEarlyAccess () }
- if ( state == "quit" ) { Qt.quit () }
- if ( state == "instance exists" ) { Qt.quit () }
- if ( state == "noKeychain" ) { Qt.quit () }
- if ( state == "checkUpdates" ) { }
- }
- }
-
- Keys.onPressed: {
- if (event.key == Qt.Key_Enter) {
- root.confirmed()
- }
- }
-}
diff --git a/internal/frontend/qml/BridgeUI/HelpView.qml b/internal/frontend/qml/BridgeUI/HelpView.qml
deleted file mode 100644
index daa7b8e9..00000000
--- a/internal/frontend/qml/BridgeUI/HelpView.qml
+++ /dev/null
@@ -1,143 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// List the settings
-
-import QtQuick 2.8
-import BridgeUI 1.0
-import ProtonUI 1.0
-
-Item {
- id: root
-
- // must have wrapper
- Rectangle {
- id: wrapper
- anchors.centerIn: parent
- width: parent.width
- height: parent.height
- color: Style.main.background
-
- // content
- Column {
- anchors.horizontalCenter : parent.horizontalCenter
-
- ButtonIconText {
- id: logs
- anchors.left: parent.left
- text: qsTr("Logs", "title of button that takes user to logs directory")
- leftIcon.text : Style.fa.align_justify
- rightIcon.text : Style.fa.chevron_circle_right
- rightIcon.font.pointSize : Style.settings.toggleSize * Style.pt
- onClicked: go.openLogs()
- }
-
- ButtonIconText {
- id: bugreport
- anchors.left: parent.left
- text: qsTr("Report Bug", "title of button that takes user to bug report form")
- leftIcon.text : Style.fa.bug
- rightIcon.text : Style.fa.chevron_circle_right
- rightIcon.font.pointSize : Style.settings.toggleSize * Style.pt
- onClicked: bugreportWin.show()
- }
-
- ButtonIconText {
- id: manual
- anchors.left: parent.left
- text: qsTr("Setup Guide", "title of button that opens setup and installation guide")
- leftIcon.text : Style.fa.book
- rightIcon.text : Style.fa.chevron_circle_right
- rightIcon.font.pointSize : Style.settings.toggleSize * Style.pt
- onClicked: go.openManual()
- }
-
- ButtonIconText {
- id: updates
- anchors.left: parent.left
- text: qsTr("Check for Updates", "title of button to check for any app updates")
- leftIcon.text : Style.fa.refresh
- rightIcon.text : Style.fa.chevron_circle_right
- rightIcon.font.pointSize : Style.settings.toggleSize * Style.pt
- onClicked: {
- go.checkForUpdates()
- }
- }
-
- // Bottom version notes
- Rectangle {
- anchors.horizontalCenter : parent.horizontalCenter
- height: viewAccount.separatorNoAccount - 3.2*manual.height
- width: wrapper.width
- color : "transparent"
- AccessibleText {
- anchors {
- bottom: parent.bottom
- horizontalCenter: parent.horizontalCenter
- }
- color: Style.main.textDisabled
- horizontalAlignment: Qt.AlignHCenter
- font.pointSize : Style.main.fontSize * Style.pt
- text:
- "ProtonMail Bridge "+go.getBackendVersion()+"\n"+
- "© 2021 Proton Technologies AG"
- }
- }
- Row {
- anchors.left : parent.left
-
- Rectangle { height: Style.dialog.spacing; width: (wrapper.width - credits.width - licenseFile.width - release.width - sepaCreditsRelease.width)/2; color: "transparent"}
-
- ClickIconText {
- id:credits
- iconText : ""
- text : qsTr("Credits", "link to click on to view list of credited libraries")
- textColor : Style.main.textDisabled
- fontSize : Style.main.fontSize
- textUnderline : true
- onClicked : winMain.dialogCredits.show()
- }
-
- Rectangle {id: sepaLicenseFile ; height: Style.dialog.spacing; width: Style.main.dummy; color: "transparent"}
-
- ClickIconText {
- id:licenseFile
- iconText : ""
- text : qsTr("License", "link to click on to view license file")
- textColor : Style.main.textDisabled
- fontSize : Style.main.fontSize
- textUnderline : true
- onClicked : {
- go.openLicenseFile()
- }
- }
-
- Rectangle {id: sepaCreditsRelease ; height: Style.dialog.spacing; width: Style.main.dummy; color: "transparent"}
-
- ClickIconText {
- id:release
- iconText : ""
- text : qsTr("Release notes", "link to click on to view release notes for this version of the app")
- textColor : Style.main.textDisabled
- fontSize : Style.main.fontSize
- textUnderline : true
- onClicked : gui.openReleaseNotes()
- }
- }
- }
- }
-}
diff --git a/internal/frontend/qml/BridgeUI/InfoWindow.qml b/internal/frontend/qml/BridgeUI/InfoWindow.qml
deleted file mode 100644
index 4035f0fd..00000000
--- a/internal/frontend/qml/BridgeUI/InfoWindow.qml
+++ /dev/null
@@ -1,144 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// Window for imap and smtp settings
-
-import QtQuick 2.8
-import QtQuick.Window 2.2
-import BridgeUI 1.0
-import ProtonUI 1.0
-
-
-Window {
- id:root
- width : Style.info.width
- height : Style.info.height
- minimumWidth : Style.info.width
- minimumHeight : Style.info.height
- maximumWidth : Style.info.width
- maximumHeight : Style.info.height
- color: "transparent"
- flags : Qt.Window | Qt.Dialog | Qt.FramelessWindowHint
- title : address
-
- Accessible.role: Accessible.Window
- Accessible.name: qsTr("Configuration information for %1").arg(address)
- Accessible.description: Accessible.name
-
- property QtObject accData : QtObject { // avoid null-pointer error
- property string account : "undef"
- property string aliases : "undef"
- property string hostname : "undef"
- property string password : "undef"
- property int portIMAP : 0
- property int portSMTP : 0
- }
- property string address : "undef"
- property int indexAccount : 0
- property int indexAddress : 0
-
- WindowTitleBar {
- id: titleBar
- window: root
- }
-
- Rectangle { // background
- color: Style.main.background
- anchors {
- left : parent.left
- right : parent.right
- top : titleBar.bottom
- bottom : parent.bottom
- }
- border {
- width: Style.main.border
- color: Style.tabbar.background
- }
- }
-
- // info content
- Column {
- anchors {
- left: parent.left
- top: titleBar.bottom
- leftMargin: Style.main.leftMargin
- topMargin: Style.info.topMargin
- }
- width : root.width - Style.main.leftMargin - Style.main.rightMargin
-
- TextLabel { text: qsTr("IMAP SETTINGS", "title of the portion of the configuration screen that contains IMAP settings"); state: "heading" }
- Rectangle { width: parent.width; height: Style.info.topMargin; color: "#00000000"}
- Grid {
- columns: 2
- rowSpacing: Style.main.fontSize
- TextLabel { text: qsTr("Hostname", "in configuration screen, displays the server hostname (127.0.0.1)") + ":"} TextValue { text: root.accData.hostname }
- TextLabel { text: qsTr("Port", "in configuration screen, displays the server port (ex. 1025)") + ":"} TextValue { text: root.accData.portIMAP }
- TextLabel { text: qsTr("Username", "in configuration screen, displays the username to use with the desktop client") + ":"} TextValue { text: root.address }
- TextLabel { text: qsTr("Password", "in configuration screen, displays the Bridge password to use with the desktop client") + ":"} TextValue { text: root.accData.password }
- TextLabel { text: qsTr("Security", "in configuration screen, displays the IMAP security settings") + ":"} TextValue { text: "STARTTLS" }
- }
- Rectangle { width: Style.main.dummy; height: Style.main.fontSize; color: "#00000000"}
- Rectangle { width: Style.main.dummy; height: Style.info.topMargin; color: "#00000000"}
-
- TextLabel { text: qsTr("SMTP SETTINGS", "title of the portion of the configuration screen that contains SMTP settings"); state: "heading" }
- Rectangle { width: Style.main.dummy; height: Style.info.topMargin; color: "#00000000"}
- Grid {
- columns: 2
- rowSpacing: Style.main.fontSize
- TextLabel { text: qsTr("Hostname", "in configuration screen, displays the server hostname (127.0.0.1)") + ":"} TextValue { text: root.accData.hostname }
- TextLabel { text: qsTr("Port", "in configuration screen, displays the server port (ex. 1025)") + ":"} TextValue { text: root.accData.portSMTP }
- TextLabel { text: qsTr("Username", "in configuration screen, displays the username to use with the desktop client") + ":"} TextValue { text: root.address }
- TextLabel { text: qsTr("Password", "in configuration screen, displays the Bridge password to use with the desktop client") + ":"} TextValue { text: root.accData.password }
- TextLabel { text: qsTr("Security", "in configuration screen, displays the SMTP security settings") + ":"} TextValue { text: go.isSMTPSTARTTLS() ? "STARTTLS" : "SSL" }
- }
- Rectangle { width: Style.main.dummy; height: Style.main.fontSize; color: "#00000000"}
- Rectangle { width: Style.main.dummy; height: Style.info.topMargin; color: "#00000000"}
- }
-
- // apple mail button
- ButtonRounded{
- anchors {
- horizontalCenter: parent.horizontalCenter
- bottom: parent.bottom
- bottomMargin: Style.info.topMargin
- }
- color_main : Style.main.textBlue
- isOpaque: false
- text: qsTr("Configure Apple Mail", "button on configuration screen to automatically configure Apple Mail")
- height: Style.main.fontSize*2
- width: 2*parent.width/3
- onClicked: {
- go.configureAppleMail(root.indexAccount, root.indexAddress)
- }
- visible: go.goos == "darwin"
- }
-
-
- function showInfo(iAccount, iAddress) {
- root.indexAccount = iAccount
- root.indexAddress = iAddress
- root.accData = accountsModel.get(iAccount)
- root.address = accData.aliases.split(";")[iAddress]
- root.show()
- root.raise()
- root.requestActivate()
- }
-
- function hide() {
- root.visible = false
- }
-}
diff --git a/internal/frontend/qml/BridgeUI/MainWindow.qml b/internal/frontend/qml/BridgeUI/MainWindow.qml
deleted file mode 100644
index 3e459979..00000000
--- a/internal/frontend/qml/BridgeUI/MainWindow.qml
+++ /dev/null
@@ -1,395 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// This is main window
-
-import QtQuick 2.8
-import QtQuick.Window 2.2
-import QtQuick.Controls 2.1
-import QtQuick.Layouts 1.3
-import BridgeUI 1.0
-import ProtonUI 1.0
-
-
-// Main Window
-Window {
- id: root
- property alias tabbar : tabbar
- property alias viewContent : viewContent
- property alias viewAccount : viewAccount
- property alias dialogAddUser : dialogAddUser
- property alias dialogChangePort : dialogChangePort
- property alias dialogCredits : dialogCredits
- property alias dialogTlsCert : dialogTlsCert
- property alias dialogUpdate : dialogUpdate
- property alias dialogFirstStart : dialogFirstStart
- property alias dialogGlobal : dialogGlobal
- property alias dialogConnectionTroubleshoot : dialogConnectionTroubleshoot
- property alias bubbleNote : bubbleNote
- property alias addAccountTip : addAccountTip
- property alias updateState : infoBar.state
- property alias tlsBarState : tlsBar.state
- property int heightContent : height-titleBar.height
-
- // main window appeareance
- width : Style.main.width
- height : Style.main.height
- flags : Qt.Window | Qt.FramelessWindowHint
- color: go.goos=="windows" ? "black" : "transparent"
- title: go.programTitle
- minimumWidth: Style.main.width
- minimumHeight: Style.main.height
- maximumWidth: Style.main.width
-
- property bool isOutdateVersion : root.updateState == "forceUpdate"
-
- property bool activeContent :
- !dialogAddUser .visible &&
- !dialogChangePort .visible &&
- !dialogCredits .visible &&
- !dialogTlsCert .visible &&
- !dialogUpdate .visible &&
- !dialogFirstStart .visible &&
- !dialogGlobal .visible &&
- !bubbleNote .visible
-
- Accessible.role: Accessible.Grouping
- Accessible.description: qsTr("Window %1").arg(title)
- Accessible.name: Accessible.description
-
-
- Component.onCompleted : {
- gui.winMain = root
- console.log("GraphicsInfo of", titleBar,
- "api" , titleBar.GraphicsInfo.api ,
- "majorVersion" , titleBar.GraphicsInfo.majorVersion ,
- "minorVersion" , titleBar.GraphicsInfo.minorVersion ,
- "profile" , titleBar.GraphicsInfo.profile ,
- "renderableType" , titleBar.GraphicsInfo.renderableType ,
- "shaderCompilationType" , titleBar.GraphicsInfo.shaderCompilationType ,
- "shaderSourceType" , titleBar.GraphicsInfo.shaderSourceType ,
- "shaderType" , titleBar.GraphicsInfo.shaderType)
-
- tabbar.focusButton()
- }
-
- WindowTitleBar {
- id: titleBar
- window: root
- }
-
- Rectangle {
- anchors {
- top : titleBar.bottom
- left : parent.left
- right : parent.right
- bottom : parent.bottom
- }
- color: Style.title.background
- }
-
- TLSCertPinIssueBar {
- id: tlsBar
- anchors {
- left : parent.left
- right : parent.right
- top : titleBar.bottom
- leftMargin: Style.main.border
- rightMargin: Style.main.border
- }
- enabled : root.activeContent
- }
-
- InformationBar {
- id: infoBar
- anchors {
- left : parent.left
- right : parent.right
- top : tlsBar.bottom
- leftMargin: Style.main.border
- rightMargin: Style.main.border
- }
- enabled : root.activeContent
- }
-
-
- TabLabels {
- id: tabbar
- currentIndex : 0
- enabled: root.activeContent
- anchors {
- top : infoBar.bottom
- right : parent.right
- left : parent.left
- leftMargin: Style.main.border
- rightMargin: Style.main.border
- }
- model: [
- { "title" : qsTr("Accounts" , "title of tab that shows account list" ), "iconText": Style.fa.user_circle_o },
- { "title" : qsTr("Settings" , "title of tab that allows user to change settings" ), "iconText": Style.fa.cog },
- { "title" : qsTr("Help" , "title of tab that shows the help menu" ), "iconText": Style.fa.life_ring }
- ]
- }
-
- // Content of tabs
- StackLayout {
- id: viewContent
- enabled: root.activeContent
- // dimensions
- anchors {
- left : parent.left
- right : parent.right
- top : tabbar.bottom
- bottom : parent.bottom
- leftMargin: Style.main.border
- rightMargin: Style.main.border
- bottomMargin: Style.main.border
- }
- // attributes
- currentIndex : { return root.tabbar.currentIndex}
- clip : true
- // content
- AccountView {
- id: viewAccount
- onAddAccount: dialogAddUser.show()
- model: accountsModel
- delegate: AccountDelegate {
- row_width: viewContent.width
- }
- }
-
- SettingsView { id: viewSettings; }
- HelpView { id: viewHelp; }
- }
-
-
- // Floating things
-
- // Triangle
- Rectangle {
- id: tabtriangle
- visible: false
- property int margin : Style.main.leftMargin+ Style.tabbar.widthButton/2
- anchors {
- top : tabbar.bottom
- left : tabbar.left
- leftMargin : tabtriangle.margin - tabtriangle.width/2 + tabbar.currentIndex * tabbar.spacing
- }
- width: 2*Style.tabbar.heightTriangle
- height: Style.tabbar.heightTriangle
- color: "transparent"
- Canvas {
- anchors.fill: parent
- onPaint: {
- var ctx = getContext("2d")
- ctx.fillStyle = Style.tabbar.background
- ctx.moveTo(0 , 0)
- ctx.lineTo(width/2, height)
- ctx.lineTo(width , 0)
- ctx.closePath()
- ctx.fill()
- }
- }
- }
-
- // Bubble prevent action
- Rectangle {
- anchors {
- left: parent.left
- right: parent.right
- top: titleBar.bottom
- bottom: parent.bottom
- }
- visible: bubbleNote.visible
- color: "#aa222222"
- MouseArea {
- anchors.fill: parent
- hoverEnabled: true
- }
- }
- BubbleNote {
- id : bubbleNote
- visible : false
- Component.onCompleted : {
- bubbleNote.place(0)
- }
- }
-
- BubbleNote {
- id:addAccountTip
- anchors.topMargin: viewAccount.separatorNoAccount - 2*Style.main.fontSize
- text : qsTr("Click here to start", "on first launch, this is displayed above the Add Account button to tell the user what to do first")
- state: (go.isFirstStart && viewAccount.numAccounts==0 && root.viewContent.currentIndex==0) ? "Visible" : "Invisible"
- bubbleColor: Style.main.textBlue
-
- Component.onCompleted : {
- addAccountTip.place(-1)
- }
- enabled: false
-
- states: [
- State {
- name: "Visible"
- // hack: opacity 100% makes buttons dialog windows quit wrong color
- PropertyChanges{target: addAccountTip; opacity: 0.999; visible: true}
- },
- State {
- name: "Invisible"
- PropertyChanges{target: addAccountTip; opacity: 0.0; visible: false}
- }
- ]
-
- transitions: [
- Transition {
- from: "Visible"
- to: "Invisible"
-
- SequentialAnimation{
- NumberAnimation {
- target: addAccountTip
- property: "opacity"
- duration: 0
- easing.type: Easing.InOutQuad
- }
- NumberAnimation {
- target: addAccountTip
- property: "visible"
- duration: 0
- }
- }
- },
- Transition {
- from: "Invisible"
- to: "Visible"
- SequentialAnimation{
- NumberAnimation {
- target: addAccountTip
- property: "visible"
- duration: 300
- }
- NumberAnimation {
- target: addAccountTip
- property: "opacity"
- duration: 500
- easing.type: Easing.InOutQuad
- }
- }
- }
- ]
- }
-
- // Dialogs
- DialogFirstStart {
- id: dialogFirstStart
- visible: go.isFirstStart && gui.isFirstWindow && !dialogGlobal.visible
- }
-
- // Dialogs
- DialogPortChange {
- id: dialogChangePort
- }
-
- DialogKeychainChange {
- id: dialogChangeKeychain
- }
-
- DialogConnectionTroubleshoot {
- id: dialogConnectionTroubleshoot
- }
-
- DialogAddUser {
- id: dialogAddUser
- onCreateAccount: Qt.openUrlExternally("https://protonmail.com/signup")
- }
-
- DialogUpdate {
- id: dialogUpdate
- forceUpdate: root.isOutdateVersion
- }
-
-
- Dialog {
- id: dialogCredits
- title: qsTr("Credits", "link to click on to view list of credited libraries")
- Credits { }
- }
-
- DialogTLSCertInfo {
- id: dialogTlsCert
- }
-
- DialogYesNo {
- id: dialogGlobal
- question : ""
- answer : ""
- z: 100
- }
-
-
- // resize
- MouseArea {
- property int diff: 0
- anchors {
- bottom : parent.bottom
- left : parent.left
- right : parent.right
- }
- cursorShape: Qt.SizeVerCursor
- height: Style.main.fontSize
- onPressed: {
- var globPos = mapToGlobal(mouse.x, mouse.y)
- diff = root.height
- diff -= globPos.y
- }
- onMouseYChanged : {
- var globPos = mapToGlobal(mouse.x, mouse.y)
- root.height = Math.max(root.minimumHeight, globPos.y + diff)
- }
- }
-
- function showAndRise(){
- go.loadAccounts()
- root.show()
- root.raise()
- if (!root.active) {
- root.requestActivate()
- }
- }
-
- // Toggle window
- function toggle() {
- go.loadAccounts()
- if (root.visible) {
- if (!root.active) {
- root.raise()
- root.requestActivate()
- } else {
- root.hide()
- }
- } else {
- root.show()
- root.raise()
- }
- }
-
- onClosing: {
- close.accepted = false
- // NOTE: In order to make an initial accounts load
- root.hide()
- gui.closeMainWindow()
- }
-}
diff --git a/internal/frontend/qml/BridgeUI/ManualWindow.qml b/internal/frontend/qml/BridgeUI/ManualWindow.qml
deleted file mode 100644
index 9632b56a..00000000
--- a/internal/frontend/qml/BridgeUI/ManualWindow.qml
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
diff --git a/internal/frontend/qml/BridgeUI/OutgoingNoEncPopup.qml b/internal/frontend/qml/BridgeUI/OutgoingNoEncPopup.qml
deleted file mode 100644
index 83647536..00000000
--- a/internal/frontend/qml/BridgeUI/OutgoingNoEncPopup.qml
+++ /dev/null
@@ -1,148 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// Popup
-
-import QtQuick 2.8
-import QtQuick.Window 2.2
-import BridgeUI 1.0
-import ProtonUI 1.0
-
-Window {
- id:root
- width : Style.info.width
- height : Style.info.width/1.5
- minimumWidth : Style.info.width
- minimumHeight : Style.info.width/1.5
- maximumWidth : Style.info.width
- maximumHeight : Style.info.width/1.5
- color : Style.main.background
- flags : Qt.Window | Qt.Popup | Qt.FramelessWindowHint
- visible : false
- title : ""
- x: 10
- y: 10
- property string messageID: ""
-
- // Drag and move
- MouseArea {
- property point diff: "0,0"
- property QtObject window: root
-
- anchors {
- fill: parent
- }
-
- onPressed: {
- diff = Qt.point(window.x, window.y)
- var mousePos = mapToGlobal(mouse.x, mouse.y)
- diff.x -= mousePos.x
- diff.y -= mousePos.y
- }
-
- onPositionChanged: {
- var currPos = mapToGlobal(mouse.x, mouse.y)
- window.x = currPos.x + diff.x
- window.y = currPos.y + diff.y
- }
- }
-
- Column {
- topPadding: Style.main.fontSize
- spacing: (root.height - (description.height + cancel.height + countDown.height + Style.main.fontSize))/3
- width: root.width
-
- Text {
- id: description
- color : Style.main.text
- font.pointSize : Style.main.fontSize*Style.pt/1.2
- anchors.horizontalCenter : parent.horizontalCenter
- horizontalAlignment : Text.AlignHCenter
- width : root.width - 2*Style.main.leftMargin
- wrapMode : Text.Wrap
- textFormat : Text.RichText
-
- text: qsTr("The message with subject %1 has one or more recipients with no encryption settings. If you do not want to send this email click the cancel button.").arg(""+root.title+"
")
- }
-
- Row {
- spacing : Style.dialog.spacing
- anchors.horizontalCenter: parent.horizontalCenter
-
- ButtonRounded {
- id: sendAnyway
- onClicked : root.hide(true)
- height: Style.main.fontSize*2
- //width: Style.dialog.widthButton*1.3
- fa_icon: Style.fa.send
- text: qsTr("Send now", "Confirmation of sending unencrypted email.")
- }
-
- ButtonRounded {
- id: cancel
- onClicked : root.hide(false)
- height: Style.main.fontSize*2
- //width: Style.dialog.widthButton*1.3
- fa_icon: Style.fa.times
- text: qsTr("Cancel", "Cancel the sending of current email")
- }
- }
-
- Text {
- id: countDown
- color: Style.main.text
- font.pointSize : Style.main.fontSize*Style.pt/1.2
- anchors.horizontalCenter : parent.horizontalCenter
- horizontalAlignment : Text.AlignHCenter
- width : root.width - 2*Style.main.leftMargin
- wrapMode : Text.Wrap
- textFormat : Text.RichText
-
- text: qsTr("This popup will close after %1 and email will be sent unless you click the cancel button.").arg( "" + timer.secLeft + "s")
- }
- }
-
- Timer {
- id: timer
- property var secLeft: 0
- interval: 1000 //ms
- repeat: true
- onTriggered: {
- secLeft--
- if (secLeft <= 0) {
- root.hide(true)
- }
- }
- }
-
- function hide(shouldSend) {
- root.visible = false
- timer.stop()
- go.saveOutgoingNoEncPopupCoord(root.x, root.y)
- go.shouldSendAnswer(root.messageID, shouldSend)
- }
-
- function show(messageID, subject) {
- root.messageID = messageID
- root.title = subject
- root.visible = true
- timer.secLeft = 10
- timer.start()
- }
-}
-
-
diff --git a/internal/frontend/qml/BridgeUI/SettingsView.qml b/internal/frontend/qml/BridgeUI/SettingsView.qml
deleted file mode 100644
index 185af589..00000000
--- a/internal/frontend/qml/BridgeUI/SettingsView.qml
+++ /dev/null
@@ -1,263 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// List the settings
-
-import QtQuick 2.8
-import BridgeUI 1.0
-import ProtonUI 1.0
-import QtQuick.Controls 2.4
-
-Item {
- id: root
-
- // must have wrapper
- ScrollView {
- id: wrapper
- anchors.centerIn: parent
- width: parent.width
- height: parent.height
- clip: true
- background: Rectangle {
- color: Style.main.background
- }
-
- // horizontall scrollbar sometimes showes up when vertical scrollbar coveres content
- ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
- ScrollBar.vertical.policy: ScrollBar.AsNeeded
-
- // keeping vertical scrollbar allways visible when needed
- Connections {
- target: wrapper.ScrollBar.vertical
- onSizeChanged: {
- // ScrollBar.size == 0 at creating so no need to make it active
- if (wrapper.ScrollBar.vertical.size < 1.0 && wrapper.ScrollBar.vertical.size > 0 && !wrapper.ScrollBar.vertical.active) {
- wrapper.ScrollBar.vertical.active = true
- }
- }
- onActiveChanged: {
- wrapper.ScrollBar.vertical.active = true
- }
- }
-
- // content
- Column {
- anchors.left : parent.left
-
- ButtonIconText {
- id: cacheClear
- text: qsTr("Clear Cache", "button to clear cache in settings")
- leftIcon.text : Style.fa.times
- rightIcon {
- text : qsTr("Clear", "clickable link next to clear cache button in settings")
- color: Style.main.text
- font {
- family : cacheClear.font.family // use default font, not font-awesome
- pointSize : Style.settings.fontSize * Style.pt
- underline : true
- }
- }
- onClicked: {
- dialogGlobal.state="clearCache"
- dialogGlobal.show()
- }
- }
-
- ButtonIconText {
- id: cacheKeychain
- text: qsTr("Clear Keychain", "button to clear keychain in settings")
- leftIcon.text : Style.fa.chain_broken
- rightIcon {
- text : qsTr("Clear", "clickable link next to clear keychain button in settings")
- color: Style.main.text
- font {
- family : cacheKeychain.font.family // use default font, not font-awesome
- pointSize : Style.settings.fontSize * Style.pt
- underline : true
- }
- }
- onClicked: {
- dialogGlobal.state="clearChain"
- dialogGlobal.show()
- }
- }
-
- ButtonIconText {
- id: autoStart
- text: qsTr("Automatically start Bridge", "label for toggle that activates and disables the automatic start")
- leftIcon.text : Style.fa.rocket
- rightIcon {
- font.pointSize : Style.settings.toggleSize * Style.pt
- text : go.isAutoStart!=false ? Style.fa.toggle_on : Style.fa.toggle_off
- color : go.isAutoStart!=false ? Style.main.textBlue : Style.main.textDisabled
- }
- Accessible.description: (
- go.isAutoStart == false ?
- qsTr("Enable" , "Click to enable the automatic start of Bridge") :
- qsTr("Disable" , "Click to disable the automatic start of Bridge")
- ) + " " + text
- onClicked: {
- go.toggleAutoStart()
- }
- }
-
- ButtonIconText {
- id: autoUpdates
- text: qsTr("Keep the application up to date", "label for toggle that activates and disables the automatic updates")
- leftIcon.text : Style.fa.download
- rightIcon {
- font.pointSize : Style.settings.toggleSize * Style.pt
- text : go.isAutoUpdate!=false ? Style.fa.toggle_on : Style.fa.toggle_off
- color : go.isAutoUpdate!=false ? Style.main.textBlue : Style.main.textDisabled
- }
- Accessible.description: (
- go.isAutoUpdate == false ?
- qsTr("Enable" , "Click to enable the automatic update of Bridge") :
- qsTr("Disable" , "Click to disable the automatic update of Bridge")
- ) + " " + text
- onClicked: {
- go.toggleAutoUpdate()
- }
- }
-
- ButtonIconText {
- id: earlyAccess
- text: qsTr("Early access", "label for toggle that enables and disables early access")
- leftIcon.text : Style.fa.star
- rightIcon {
- font.pointSize : Style.settings.toggleSize * Style.pt
- text : go.isEarlyAccess!=false ? Style.fa.toggle_on : Style.fa.toggle_off
- color : go.isEarlyAccess!=false ? Style.main.textBlue : Style.main.textDisabled
- }
- Accessible.description: (
- go.isEarlyAccess == false ?
- qsTr("Enable" , "Click to enable early access") :
- qsTr("Disable" , "Click to disable early access")
- ) + " " + text
- onClicked: {
- if (go.isEarlyAccess == true) {
- dialogGlobal.state="toggleEarlyAccessOff"
- dialogGlobal.show()
- } else {
- dialogGlobal.state="toggleEarlyAccessOn"
- dialogGlobal.show()
- }
- }
- }
-
- ButtonIconText {
- id: advancedSettings
- property bool isAdvanced : !go.isDefaultPort
- text: qsTr("Advanced settings", "button to open the advanced settings list in the settings page")
- leftIcon.text : Style.fa.cogs
- rightIcon {
- font.pointSize : Style.settings.toggleSize * Style.pt
- text : isAdvanced!=0 ? Style.fa.chevron_circle_up : Style.fa.chevron_circle_right
- color : isAdvanced!=0 ? Style.main.textDisabled : Style.main.textBlue
- }
-
- Accessible.description: (
- isAdvanced ?
- qsTr("Hide", "Click to hide the advance settings") :
- qsTr("Show", "Click to show the advance settings")
- ) + " " + text
- onClicked: {
- isAdvanced = !isAdvanced
- }
- }
-
- ButtonIconText {
- id: changePort
- visible: advancedSettings.isAdvanced
- text: qsTr("Change IMAP & SMTP settings", "button to change IMAP and SMTP ports in settings")
- leftIcon.text : Style.fa.plug
- rightIcon {
- text : qsTr("Change", "clickable link next to change ports button in settings")
- color: Style.main.text
- font {
- family : changePort.font.family // use default font, not font-awesome
- pointSize : Style.settings.fontSize * Style.pt
- underline : true
- }
- }
- onClicked: {
- dialogChangePort.show()
- }
- }
-
- ButtonIconText {
- id: reportNoEnc
- text: qsTr("Notification of outgoing email without encryption", "Button to set whether to report or send an email without encryption")
- visible: advancedSettings.isAdvanced
- leftIcon.text : Style.fa.ban
- rightIcon {
- font.pointSize : Style.settings.toggleSize * Style.pt
- text : go.isReportingOutgoingNoEnc ? Style.fa.toggle_on : Style.fa.toggle_off
- color : go.isReportingOutgoingNoEnc ? Style.main.textBlue : Style.main.textDisabled
- }
- Accessible.description: (
- go.isReportingOutgoingNoEnc == 0 ?
- qsTr("Enable" , "Click to report an email without encryption") :
- qsTr("Disable" , "Click to send without asking an email without encryption")
- ) + " " + text
- onClicked: {
- go.toggleIsReportingOutgoingNoEnc()
- }
- }
-
- ButtonIconText {
- id: allowProxy
- visible: advancedSettings.isAdvanced
- text: qsTr("Allow alternative routing", "label for toggle that allows and disallows using a proxy")
- leftIcon.text : Style.fa.rocket
- rightIcon {
- font.pointSize : Style.settings.toggleSize * Style.pt
- text : go.isProxyAllowed!=false ? Style.fa.toggle_on : Style.fa.toggle_off
- color : go.isProxyAllowed!=false ? Style.main.textBlue : Style.main.textDisabled
- }
- Accessible.description: (
- go.isProxyAllowed == false ?
- qsTr("Enable" , "Click to allow alternative routing") :
- qsTr("Disable" , "Click to disallow alternative routing")
- ) + " " + text
- onClicked: {
- dialogGlobal.state="toggleAllowProxy"
- dialogGlobal.show()
- }
- }
-
- ButtonIconText {
- id: changeKeychain
- visible: advancedSettings.isAdvanced && (go.availableKeychain.length > 1)
- text: qsTr("Change keychain", "button to open dialog with default keychain selection")
- leftIcon.text : Style.fa.key
- rightIcon {
- text : qsTr("Change", "clickable link next to change keychain button in settings")
- color: Style.main.text
- font {
- family : changeKeychain.font.family // use default font, not font-awesome
- pointSize : Style.settings.fontSize * Style.pt
- underline : true
- }
- }
- onClicked: {
- dialogChangeKeychain.show()
- }
- }
- }
- }
-}
diff --git a/internal/frontend/qml/BridgeUI/StatusFooter.qml b/internal/frontend/qml/BridgeUI/StatusFooter.qml
deleted file mode 100644
index 9632b56a..00000000
--- a/internal/frontend/qml/BridgeUI/StatusFooter.qml
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
diff --git a/internal/frontend/qml/BridgeUI/qmldir b/internal/frontend/qml/BridgeUI/qmldir
deleted file mode 100644
index dc6067b6..00000000
--- a/internal/frontend/qml/BridgeUI/qmldir
+++ /dev/null
@@ -1,15 +0,0 @@
-module BridgeUI
-AccountDelegate 1.0 AccountDelegate.qml
-Credits 1.0 Credits.qml
-DialogFirstStart 1.0 DialogFirstStart.qml
-DialogKeychainChange 1.0 DialogKeychainChange.qml
-DialogPortChange 1.0 DialogPortChange.qml
-DialogYesNo 1.0 DialogYesNo.qml
-DialogTLSCertInfo 1.0 DialogTLSCertInfo.qml
-HelpView 1.0 HelpView.qml
-InfoWindow 1.0 InfoWindow.qml
-MainWindow 1.0 MainWindow.qml
-ManualWindow 1.0 ManualWindow.qml
-OutgoingNoEncPopup 1.0 OutgoingNoEncPopup.qml
-SettingsView 1.0 SettingsView.qml
-StatusFooter 1.0 StatusFooter.qml
diff --git a/internal/frontend/qml/Gui.qml b/internal/frontend/qml/Gui.qml
deleted file mode 100644
index 8b9df27e..00000000
--- a/internal/frontend/qml/Gui.qml
+++ /dev/null
@@ -1,378 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// This is main qml file
-
-import QtQuick 2.8
-import BridgeUI 1.0
-import ProtonUI 1.0
-
-// All imports from dynamic must be loaded before
-import QtQuick.Window 2.2
-import QtQuick.Controls 2.1
-import QtQuick.Layouts 1.3
-
-Item {
- id: gui
- property MainWindow winMain
- property bool isFirstWindow: true
- property int warningFlags: 0
-
- InfoWindow { id: infoWin }
- OutgoingNoEncPopup { id: outgoingNoEncPopup }
- BugReportWindow {
- id: bugreportWin
- clientVersion.visible : true
-
- // pre-fill the form
- onPrefill : {
- userAddress.text=""
- if (accountsModel.count>0) {
- var addressList = accountsModel.get(0).aliases.split(";")
- if (addressList.length>0) {
- userAddress.text = addressList[0]
- }
- }
- clientVersion.text=go.getLastMailClient()
- }
- }
-
- onWarningFlagsChanged : {
- if (gui.warningFlags==Style.okInfoBar) {
- go.normalSystray()
- return
- }
-
- if ((gui.warningFlags & Style.errorInfoBar) == Style.errorInfoBar) {
- go.errorSystray()
- return
- }
-
- go.highlightSystray()
- }
-
- // Signals from Go
- Connections {
- target: go
-
- onShowWindow : {
- gui.openMainWindow()
- }
- onShowHelp : {
- gui.openMainWindow(false)
- winMain.tabbar.currentIndex = 2
- winMain.showAndRise()
- }
- onShowQuit : {
- gui.openMainWindow(false)
- winMain.dialogGlobal.state="quit"
- winMain.dialogGlobal.show()
- winMain.showAndRise()
- }
-
- onProcessFinished : {
- winMain.dialogGlobal.hide()
- winMain.dialogAddUser.hide()
- winMain.dialogChangePort.hide()
- infoWin.hide()
- }
- onOpenManual : Qt.openUrlExternally("http://protonmail.com/bridge")
-
- onNotifyBubble : {
- gui.showBubble(tabIndex, message, true)
- }
- onSilentBubble : {
- gui.showBubble(tabIndex, message, false)
- }
- onBubbleClosed : {
- gui.warningFlags &= ~Style.warnBubbleMessage
- }
-
- onSetConnectionStatus: {
- go.isConnectionOK = isAvailable
- gui.openMainWindow(false)
- if (go.isConnectionOK) {
- if( winMain.updateState=="noInternet") {
- go.updateState = "upToDate"
- }
- } else {
- go.updateState = "noInternet"
- }
- }
-
- onUpdateStateChanged : {
- // Update tray icon if needed
- switch (go.updateState) {
- case "internetCheck":
- break;
- case "noInternet" :
- gui.warningFlags |= Style.warnInfoBar
- break;
- case "oldVersion":
- gui.warningFlags |= Style.warnInfoBar
- break;
- case "forceUpdate":
- // Force update should presist once it happened and never be overwritten.
- // That means that tray icon should allways remain in error state.
- // But since we have only two sources of error icon in tray (force update
- // + installation fail) and both are unrecoverable and we do not ever remove
- // error flag from gui.warningFlags - it is ok to rely on gui.warningFlags and
- // not on winMain.updateState (which presist forceUpdate)
- gui.warningFlags |= Style.errorInfoBar
- break;
- case "upToDate":
- gui.warningFlags &= ~Style.warnInfoBar
- break;
- case "updateRestart":
- gui.warningFlags |= Style.warnInfoBar
- break;
- case "updateError":
- gui.warningFlags |= Style.errorInfoBar
- break;
- default :
- break;
- }
-
- // if main window is closed - most probably it is destroyed (see closeMainWindow())
- if (winMain == null) {
- return
- }
- // once app is outdated prevent from state change
- if (winMain.updateState != "forceUpdate") {
- winMain.updateState = go.updateState
- }
- }
-
- onSetAddAccountWarning : winMain.dialogAddUser.setWarning(message, 0)
-
-
- onNotifyVersionIsTheLatest : {
- go.silentBubble(2,qsTr("You have the latest version!", "notification", -1))
- }
-
- onNotifyManualUpdate: {
- go.updateState = "oldVersion"
- }
-
- onNotifyManualUpdateRestartNeeded: {
- if (!winMain.dialogUpdate.visible) {
- winMain.dialogUpdate.show()
- }
- go.updateState = "updateRestart"
- winMain.dialogUpdate.finished(false)
-
- // after manual update - just retart immidiatly
- go.setToRestart()
- Qt.quit()
- }
-
- onNotifyManualUpdateError: {
- if (!winMain.dialogUpdate.visible) {
- winMain.dialogUpdate.show()
- }
- go.updateState = "updateError"
- winMain.dialogUpdate.finished(true)
- }
-
- onNotifyForceUpdate : {
- go.updateState = "forceUpdate"
- if (!winMain.dialogUpdate.visible) {
- winMain.dialogUpdate.show()
- }
- }
-
- onNotifySilentUpdateRestartNeeded: {
- go.updateState = "updateRestart"
- }
-
- onNotifySilentUpdateError: {
- go.updateState = "updateError"
- }
-
- onNotifyLogout : {
- go.notifyBubble(0, qsTr("Account %1 has been disconnected. Please log in to continue to use the Bridge with this account.").arg(accname) )
- }
-
- onNotifyAddressChanged : {
- go.notifyBubble(0, qsTr("The address list has been changed for account %1. You may need to reconfigure the settings in your email client.").arg(accname) )
- }
-
- onNotifyAddressChangedLogout : {
- go.notifyBubble(0, qsTr("The address list has been changed for account %1. You have to reconfigure the settings in your email client.").arg(accname) )
- }
-
- onNotifyPortIssue : { // busyPortIMAP , busyPortSMTP
- if (!busyPortIMAP && !busyPortSMTP) { // at least one must have issues to show warning
- return
- }
- gui.openMainWindow(false)
- winMain.tabbar.currentIndex=1
- go.isDefaultPort = false
- var text
- if (busyPortIMAP && busyPortSMTP) { // both have problems
- text = qsTr("The default ports used by Bridge for IMAP (%1) and SMTP (%2) are occupied by one or more other applications." , "the first part of notification text (two ports)").arg(go.getIMAPPort()).arg(go.getSMTPPort())
- text += " "
- text += qsTr("To change the ports for these servers, go to Settings -> Advanced Settings.", "the second part of notification text (two ports)")
- } else { // only one is occupied
- var server, port
- if (busyPortSMTP) {
- server = "SMTP"
- port = go.getSMTPPort()
- } else {
- server = "IMAP"
- port = go.getIMAPPort()
- }
- text = qsTr("The default port used by Bridge for %1 (%2) is occupied by another application.", "the first part of notification text (one port)").arg(server).arg(port)
- text += " "
- text += qsTr("To change the port for this server, go to Settings -> Advanced Settings.", "the second part of notification text (one port)")
- }
- go.notifyBubble(1, text )
- }
-
- onNotifyKeychainRebuild : {
- go.notifyBubble(1, qsTr(
- "Your MacOS keychain is probably corrupted. Please consult the instructions in our FAQ.",
- "notification message"
- ))
- }
-
- onNotifyHasNoKeychain : {
- gui.winMain.dialogGlobal.state="noKeychain"
- gui.winMain.dialogGlobal.show()
- }
-
- onShowNoActiveKeyForRecipient : {
- go.notifyBubble(0, qsTr(
- "Key pinning is enabled for %1 but no active key is pinned. " +
- "You must pin the key in order to send a message to this address. " +
- "You can find instructions " +
- "here."
- ).arg(recipient))
- }
-
- onFailedAutostartCode : {
- gui.openMainWindow(true)
- switch (code) {
- case "permission" : // linux+darwin
- case "85070005" : // windows
- go.notifyBubble(1, go.failedAutostartPerm)
- break
- case "81004003" : // windows
- go.notifyBubble(1, go.failedAutostart+" "+qsTr("Can not create instance.", "for autostart"))
- break
- case "" :
- default :
- go.notifyBubble(1, go.failedAutostart)
- }
- }
-
- onShowOutgoingNoEncPopup : {
- outgoingNoEncPopup.show(messageID, subject)
- }
-
- onSetOutgoingNoEncPopupCoord : {
- outgoingNoEncPopup.x = x
- outgoingNoEncPopup.y = y
- }
-
- onShowCertIssue : {
- winMain.tlsBarState="notOK"
- }
-
- onOpenReleaseNotesExternally: {
- Qt.openUrlExternally(go.updateReleaseNotesLink)
- }
-
- }
-
- function openMainWindow(showAndRise) {
- // wait and check until font is loaded
- while(true){
- if (Style.fontawesome.status == FontLoader.Loading) continue
- if (Style.fontawesome.status != FontLoader.Ready) console.log("Error while loading font")
- break
- }
-
- if (typeof(showAndRise)==='undefined') {
- showAndRise = true
- }
- if (gui.winMain == null) {
- gui.winMain = Qt.createQmlObject(
- 'import BridgeUI 1.0; MainWindow {visible : false}',
- gui, "winMain"
- )
- }
- if (showAndRise) {
- gui.winMain.showAndRise()
- }
-
- // restore update notification bar: trigger updateStateChanged
- var tmp = go.updateState
- go.updateState = ""
- go.updateState = tmp
- }
-
- function closeMainWindow () {
- // Historical reasons: once upon a time there was a report about high GPU
- // usage on MacOS while bridge is closed. Legends say that destroying
- // MainWindow solved this.
- gui.winMain.hide()
- gui.winMain.destroy(5000)
- gui.winMain = null
- gui.isFirstWindow = false
- }
-
- function showBubble(tabIndex, message, isWarning) {
- gui.openMainWindow(true)
- if (isWarning) {
- gui.warningFlags |= Style.warnBubbleMessage
- }
- winMain.bubbleNote.text = message
- winMain.bubbleNote.place(tabIndex)
- winMain.bubbleNote.show()
- }
-
- function openReleaseNotes(){
- if (go.updateReleaseNotesLink == "") {
- go.checkAndOpenReleaseNotes()
- return
- }
- go.openReleaseNotesExternally()
- }
-
-
- // On start
- Component.onCompleted : {
- // set messages for translations
- go.wrongCredentials = qsTr("Incorrect username or password." , "notification", -1)
- go.wrongMailboxPassword = qsTr("Incorrect mailbox password." , "notification", -1)
- go.canNotReachAPI = qsTr("Cannot contact server, please check your internet connection." , "notification", -1)
- go.versionCheckFailed = qsTr("Version check was unsuccessful. Please try again later." , "notification", -1)
- go.credentialsNotRemoved = qsTr("Credentials could not be removed." , "notification", -1)
- go.failedAutostartPerm = qsTr("Unable to configure automatic start due to permissions settings - see FAQ for details.", "notification", -1)
- go.failedAutostart = qsTr("Unable to configure automatic start." , "notification", -1)
- go.genericErrSeeLogs = qsTr("An error happened during procedure. See logs for more details." , "notification", -1)
-
- go.guiIsReady()
-
- // start window
- gui.openMainWindow(false)
- if (go.isShownOnStart) {
- gui.winMain.showAndRise()
- }
- }
-}
diff --git a/internal/frontend/qml/GuiIE.qml b/internal/frontend/qml/GuiIE.qml
deleted file mode 100644
index fb5c9efb..00000000
--- a/internal/frontend/qml/GuiIE.qml
+++ /dev/null
@@ -1,440 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// This is main qml file
-
-import QtQuick 2.8
-import ImportExportUI 1.0
-import ProtonUI 1.0
-
-// All imports from dynamic must be loaded before
-import QtQuick.Window 2.2
-import QtQuick.Controls 2.1
-import QtQuick.Layouts 1.3
-
-Item {
- id: gui
- property alias winMain: winMain
- property bool isFirstWindow: true
-
- property var locale : Qt.locale("en_US")
- property date netBday : new Date("1989-03-13T00:00:00")
- property var allYears : getYearList(1970,(new Date()).getFullYear())
- property var allMonths : getMonthList(1,12)
- property var allDays : getDayList(1,31)
-
- property var enums : JSON.parse('{"pathOK":1,"pathEmptyPath":2,"pathWrongPath":4,"pathNotADir":8,"pathWrongPermissions":16,"pathDirEmpty":32,"errUnknownError":0,"errEventAPILogout":1,"errUpdateAPI":2,"errUpdateJSON":3,"errUserAuth":4,"errQApplication":18,"errEmailExportFailed":6,"errEmailExportMissing":7,"errNothingToImport":8,"errEmailImportFailed":12,"errDraftImportFailed":13,"errDraftLabelFailed":14,"errEncryptMessageAttachment":15,"errEncryptMessage":16,"errNoInternetWhileImport":17,"errUnlockUser":5,"errSourceMessageNotSelected":19,"errCannotParseMail":5000,"errWrongLoginOrPassword":5001,"errWrongServerPathOrPort":5002,"errWrongAuthMethod":5003,"errIMAPFetchFailed":5004,"errLocalSourceLoadFailed":1000,"errPMLoadFailed":1001,"errRemoteSourceLoadFailed":1002,"errLoadAccountList":1005,"errExit":1006,"errRetry":1007,"errAsk":1008,"errImportFailed":1009,"errCreateLabelFailed":1010,"errCreateFolderFailed":1011,"errUpdateLabelFailed":1012,"errUpdateFolderFailed":1013,"errFillFolderName":1014,"errSelectFolderColor":1015,"errNoInternet":1016,"folderTypeSystem":"system","folderTypeLabel":"label","folderTypeFolder":"folder","folderTypeExternal":"external","progressInit":"init","progressLooping":"looping","statusNoInternet":"noInternet","statusCheckingInternet":"internetCheck","statusNewVersionAvailable":"oldVersion","statusUpToDate":"upToDate","statusForceUpdate":"forceUpdate"}')
-
- IEStyle{}
-
- MainWindow {
- id: winMain
-
- visible : true
- Component.onCompleted: {
- winMain.showAndRise()
- }
- }
-
- BugReportWindow {
- id:bugreportWin
- clientVersion.visible: false
- onPrefill : {
- userAddress.text=""
- if (accountsModel.count>0) {
- var addressList = accountsModel.get(0).aliases.split(";")
- if (addressList.length>0) {
- userAddress.text = addressList[0]
- }
- }
- }
- }
-
- // Signals from Go
- Connections {
- target: go
-
- onShowWindow : {
- winMain.showAndRise()
- }
-
- onProcessFinished : {
- winMain.dialogAddUser.hide()
- winMain.dialogGlobal.hide()
- }
- onOpenManual : Qt.openUrlExternally("https://protonmail.com/support/categories/import-export/")
-
- onNotifyBubble : {
- //go.highlightSystray()
- winMain.bubleNote.text = message
- winMain.bubleNote.place(tabIndex)
- winMain.bubleNote.show()
- winMain.showAndRise()
- }
- onBubbleClosed : {
- if (winMain.updateState=="uptodate") {
- //go.normalSystray()
- }
- }
-
- onSetConnectionStatus: {
- go.isConnectionOK = isAvailable
- if (go.isConnectionOK) {
- if( winMain.updateState==gui.enums.statusNoInternet) {
- go.updateState = gui.enums.statusUpToDate
- }
- } else {
- go.updateState = gui.enums.statusNoInternet
- }
- }
-
- onUpdateStateChanged : {
- // once app is outdated prevent from state change
- if (winMain.updateState != "forceUpdate") {
- winMain.updateState = go.updateState
- }
- }
-
- onSetAddAccountWarning : winMain.dialogAddUser.setWarning(message, 0)
-
- onNotifyVersionIsTheLatest : {
- winMain.popupMessage.show(
- qsTr("You have the latest version!", "todo")
- )
- }
-
- onNotifyError : {
- var sep = go.errorDescription.indexOf("\n") < 0 ? go.errorDescription.length : go.errorDescription.indexOf("\n")
- var name = go.errorDescription.slice(0, sep)
- var errorMessage = go.errorDescription.slice(sep)
- switch (errCode) {
- case gui.enums.errPMLoadFailed :
- winMain.popupMessage.show ( qsTr ( "Loading ProtonMail folders and labels was not successful." , "Error message" ) )
- winMain.dialogExport.hide()
- break
- case gui.enums.errLocalSourceLoadFailed :
- winMain.popupMessage.show(qsTr(
- "Loading local folder structure was not successful. "+
- "Folder does not contain valid MBOX or EML file.",
- "Error message when can not find correct files in folder."
- ))
- winMain.dialogImport.hide()
- break
- case gui.enums.errRemoteSourceLoadFailed :
- winMain.popupMessage.show ( qsTr ( "Loading remote source structure was not successful." , "Error message" ) )
- winMain.dialogImport.hide()
- break
- case gui.enums.errWrongServerPathOrPort :
- winMain.popupMessage.show ( qsTr ( "Cannot contact server - incorrect server address and port." , "Error message" ) )
- winMain.dialogImport.decrementCurrentIndex()
- break
- case gui.enums.errWrongLoginOrPassword :
- winMain.popupMessage.show ( qsTr ( "Cannot authenticate - Incorrect email or password." , "Error message" ) )
- winMain.dialogImport.decrementCurrentIndex()
- break ;
- case gui.enums.errWrongAuthMethod :
- winMain.popupMessage.show ( qsTr ( "Cannot authenticate - Please use secured authentication method." , "Error message" ) )
- winMain.dialogImport.decrementCurrentIndex()
- break ;
-
-
- case gui.enums.errFillFolderName:
- winMain.popupMessage.show(qsTr (
- "Please fill the name.",
- "Error message when user did not fill the name of folder or label"
- ))
- break
- case gui.enums.errCreateLabelFailed:
- winMain.popupMessage.show(qsTr(
- "Cannot create label with name \"%1\"\n%2",
- "Error message when it is not possible to create new label, arg1 folder name, arg2 error reason"
- ).arg(name).arg(errorMessage))
- break
- case gui.enums.errCreateFolderFailed:
- winMain.popupMessage.show(qsTr(
- "Cannot create folder with name \"%1\"\n%2",
- "Error message when it is not possible to create new folder, arg1 folder name, arg2 error reason"
- ).arg(name).arg(errorMessage))
- break
-
- case gui.enums.errNothingToImport:
- winMain.popupMessage.show ( qsTr ( "No emails left to import after date range applied. Please, change the date range to continue." , "Error message" ) )
- winMain.dialogImport.decrementCurrentIndex()
- break
-
- case gui.enums.errNoInternetWhileImport:
- case gui.enums.errNoInternet:
- go.setConnectionStatus(false)
- winMain.popupMessage.show ( go.canNotReachAPI )
- break
-
- case gui.enums.errPMAPIMessageTooLarge:
- case gui.enums.errIMAPFetchFailed:
- case gui.enums.errEmailImportFailed :
- case gui.enums.errDraftImportFailed :
- case gui.enums.errDraftLabelFailed :
- case gui.enums.errEncryptMessageAttachment:
- case gui.enums.errEncryptMessage:
- //winMain.dialogImport.ask_retry_skip_cancel(name, errorMessage)
- console.log("Import error", errCode, go.errorDescription)
- winMain.popupMessage.show(qsTr("Error during import: \n%1\n please see log files for more details.", "message of generic error").arg(go.errorDescription))
- winMain.dialogImport.hide()
- break;
-
- case gui.enums.errUnknownError : default:
- console.log("Unknown Error", errCode, go.errorDescription)
- winMain.popupMessage.show(qsTr("The program encounter an unknown error \n%1\n please see log files for more details.", "message of generic error").arg(go.errorDescription))
- winMain.dialogExport.hide()
- winMain.dialogImport.hide()
- winMain.dialogAddUser.hide()
- winMain.dialogGlobal.hide()
- }
- }
-
- onNotifyManualUpdate: {
- go.updateState = "oldVersion"
- }
-
- onNotifyManualUpdateRestartNeeded: {
- if (!winMain.dialogUpdate.visible) {
- winMain.dialogUpdate.show()
- }
- go.updateState = "updateRestart"
- winMain.dialogUpdate.finished(false)
-
- // after manual update - just retart immidiatly
- go.setToRestart()
- Qt.quit()
- }
-
- onNotifyManualUpdateError: {
- if (!winMain.dialogUpdate.visible) {
- winMain.dialogUpdate.show()
- }
- go.updateState = "updateError"
- winMain.dialogUpdate.finished(true)
- }
-
- onNotifyForceUpdate : {
- go.updateState = "forceUpdate"
- if (!winMain.dialogUpdate.visible) {
- winMain.dialogUpdate.show()
- }
- }
-
- //onNotifySilentUpdateRestartNeeded: {
- // go.updateState = "updateRestart"
- //}
- //
- //onNotifySilentUpdateError: {
- // go.updateState = "updateError"
- //}
-
- onNotifyLogout : {
- go.notifyBubble(0, qsTr("Account %1 has been disconnected. Please log in to continue to use the Import-Export app with this account.").arg(accname) )
- }
-
- onNotifyAddressChanged : {
- go.notifyBubble(0, qsTr("The address list has been changed for account %1. You may need to reconfigure the settings in your email client.").arg(accname) )
- }
-
- onNotifyAddressChangedLogout : {
- go.notifyBubble(0, qsTr("The address list has been changed for account %1. You have to reconfigure the settings in your email client.").arg(accname) )
- }
-
-
- onNotifyKeychainRebuild : {
- go.notifyBubble(1, qsTr(
- "Your MacOS keychain is probably corrupted. Please consult the instructions in our FAQ.",
- "notification message"
- ))
- }
-
- onNotifyHasNoKeychain : {
- gui.winMain.dialogGlobal.state="noKeychain"
- gui.winMain.dialogGlobal.show()
- }
-
-
- onExportStructureLoadFinished: {
- if (okay) winMain.dialogExport.okay()
- else winMain.dialogExport.cancel()
- }
- onImportStructuresLoadFinished: {
- if (okay) winMain.dialogImport.okay()
- else winMain.dialogImport.cancel()
- }
-
- onSimpleErrorHappen: {
- if (winMain.dialogImport.visible == true) {
- winMain.dialogImport.hide()
- }
- if (winMain.dialogExport.visible == true) {
- winMain.dialogExport.hide()
- }
- }
-
- onUpdateFinished : {
- winMain.dialogUpdate.finished(hasError)
- }
-
- onOpenReleaseNotesExternally: {
- Qt.openUrlExternally(go.updateReleaseNotesLink)
- }
-
-
- }
-
- function folderIcon(folderName, folderType) { // translations
- switch (folderName.toLowerCase()) {
- case "inbox" : return Style.fa.inbox
- case "sent" : return Style.fa.send
- case "spam" :
- case "junk" : return Style.fa.ban
- case "draft" : return Style.fa.file_o
- case "starred" : return Style.fa.star_o
- case "trash" : return Style.fa.trash_o
- case "archive" : return Style.fa.archive
- default: return folderType == gui.enums.folderTypeLabel ? Style.fa.tag : Style.fa.folder_open
- }
- return Style.fa.sticky_note_o
- }
-
- function folderTypeTitle(folderType) { // translations
- if (folderType==gui.enums.folderTypeSystem ) return ""
- if (folderType==gui.enums.folderTypeLabel ) return qsTr("Labels" , "todo")
- if (folderType==gui.enums.folderTypeFolder ) return qsTr("Folders" , "todo")
- return "Undef"
- }
-
- function isFolderEmpty() {
- return "true"
- }
-
- function getUnixTime(dateString) {
- var d = new Date(dateString)
- var n = d.getTime()
- if (n != n) return -1
- return n
- }
-
- function getYearList(minY,maxY) {
- var years = new Array()
- for (var i=0; i<=maxY-minY;i++) {
- years[i] = (maxY-i).toString()
- }
- //console.log("getYearList:", years)
- return years
- }
-
- function getMonthList(minM,maxM) {
- var months = new Array()
- for (var i=0; i<=maxM-minM;i++) {
- var iMonth = new Date(1989,(i+minM-1),13)
- months[i] = iMonth.toLocaleString(gui.locale, "MMM")
- }
- //console.log("getMonthList:", months[0], months)
- return months
- }
-
- function getDayList(minD,maxD) {
- var days = new Array()
- for (var i=0; i<=maxD-minD;i++) {
- days[i] = gui.prependZeros(i+minD,2)
- }
- return days
- }
-
- function prependZeros(num,desiredLength) {
- var s = num+""
- while (s.length < desiredLength) s="0"+s
- return s
- }
-
- function daysInMonth(year,month) {
- if (typeof(year) !== 'number') {
- year = parseInt(year)
- }
- if (typeof(month) !== 'number') {
- month = Date.fromLocaleDateString( gui.locale, "1970-"+month+"-10", "yyyy-MMM-dd").getMonth()+1
- }
- var maxDays = (new Date(year,month,0)).getDate()
- if (isNaN(maxDays)) maxDays = 0
- //console.log(" daysInMonth", year, month, maxDays)
- return maxDays
- }
-
- function niceDateTime() {
- var stamp = new Date()
- var nice = getMonthList(stamp.getMonth()+1, stamp.getMonth()+1)[0]
- nice += "-" + getDayList(stamp.getDate(), stamp.getDate())[0]
- nice += "-" + getYearList(stamp.getFullYear(), stamp.getFullYear())[0]
- nice += " " + gui.prependZeros(stamp.getHours(),2)
- nice += ":" + gui.prependZeros(stamp.getMinutes(),2)
- return nice
- }
-
- /*
- // Debug
- Connections {
- target: structureExternal
-
- onDataChanged: {
- console.log("external data changed")
- }
- }
-
- // Debug
- Connections {
- target: structurePM
-
- onSelectedLabelsChanged: console.log("PM sel labels:", structurePM.selectedLabels)
- onSelectedFoldersChanged: console.log("PM sel folders:", structurePM.selectedFolders)
- onDataChanged: {
- console.log("PM data changed")
- }
- }
- */
-
- function openReleaseNotes(){
- if (go.updateReleaseNotesLink == "") {
- go.checkAndOpenReleaseNotes()
- return
- }
- go.openReleaseNotesExternally()
- }
-
-
- property string areYouSureYouWantToQuit : qsTr("There are incomplete processes - some items are not yet transferred. Do you really want to stop and quit?")
- // On start
- Component.onCompleted : {
- // set spell messages
- go.wrongCredentials = qsTr("Incorrect username or password." , "notification", -1)
- go.wrongMailboxPassword = qsTr("Incorrect mailbox password." , "notification", -1)
- go.canNotReachAPI = qsTr("Cannot contact server, please check your internet connection." , "notification", -1)
- go.versionCheckFailed = qsTr("Version check was unsuccessful. Please try again later." , "notification", -1)
- go.credentialsNotRemoved = qsTr("Credentials could not be removed." , "notification", -1)
- go.bugNotSent = qsTr("Unable to submit bug report." , "notification", -1)
- go.bugReportSent = qsTr("Bug report successfully sent." , "notification", -1)
-
-
- go.guiIsReady()
-
- gui.allMonths = getMonthList(1,12)
- gui.allMonthsChanged()
- }
-}
diff --git a/internal/frontend/qml/ImportExportUI/AccountDelegate.qml b/internal/frontend/qml/ImportExportUI/AccountDelegate.qml
deleted file mode 100644
index 25dcca75..00000000
--- a/internal/frontend/qml/ImportExportUI/AccountDelegate.qml
+++ /dev/null
@@ -1,435 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-import QtQuick 2.8
-import ProtonUI 1.0
-import ImportExportUI 1.0
-
-// NOTE: Keep the Column so the height and width is inherited from content
-Column {
- id: root
- state: status
- anchors.left: parent.left
-
- property real row_width: 50 * Style.px
- property int row_height: Style.accounts.heightAccount
- property var listalias : aliases.split(";")
- property int iAccount: index
-
- property real spacingLastButtons: (row_width - exportAccount.anchors.leftMargin -Style.main.rightMargin - exportAccount.width - logoutAccount.width - deleteAccount.width)/2
-
- Accessible.role: go.goos=="windows" ? Accessible.Grouping : Accessible.Row
- Accessible.name: qsTr("Account %1, status %2", "Accessible text describing account row with arguments: account name and status (connected/disconnected), resp.").arg(account).arg(statusMark.text)
- Accessible.description: Accessible.name
- Accessible.ignored: !enabled || !visible
-
- // Main row
- Rectangle {
- id: mainaccRow
- anchors.left: parent.left
- width : row_width
- height : row_height
- state: { return isExpanded ? "expanded" : "collapsed" }
- color: Style.main.background
-
- property string actionName : (
- isExpanded ?
- qsTr("Collapse row for account %2", "Accessible text of button showing additional configuration of account") :
- qsTr("Expand row for account %2", "Accessible text of button hiding additional configuration of account")
- ). arg(account)
-
-
- // override by other buttons
- MouseArea {
- id: mouseArea
- anchors.fill: parent
- onClicked : {
- if (root.state=="connected") {
- mainaccRow.toggle_accountSettings()
- }
- }
- cursorShape : root.state == "connected" ? Qt.PointingHandCursor : Qt.ArrowCursor
- hoverEnabled: true
- onEntered: {
- if (mainaccRow.state=="collapsed") {
- mainaccRow.color = Qt.lighter(Style.main.background,1.1)
- }
- }
- onExited: {
- if (mainaccRow.state=="collapsed") {
- mainaccRow.color = Style.main.background
- }
- }
- }
-
- // toggle down/up icon
- Text {
- id: toggleIcon
- anchors {
- left : parent.left
- verticalCenter : parent.verticalCenter
- leftMargin : Style.main.leftMargin
- }
- color: Style.main.text
- font {
- pointSize : Style.accounts.sizeChevron * Style.pt
- family : Style.fontawesome.name
- }
- text: Style.fa.chevron_down
-
- MouseArea {
- anchors.fill: parent
- onClicked : {
- if (root.state=="connected") {
- mainaccRow.toggle_accountSettings()
- }
- }
- cursorShape : root.state == "connected" ? Qt.PointingHandCursor : Qt.ArrowCursor
- Accessible.role: Accessible.Button
- Accessible.name: mainaccRow.actionName
- Accessible.description: mainaccRow.actionName
- Accessible.onPressAction : {
- if (root.state=="connected") {
- mainaccRow.toggle_accountSettings()
- }
- }
- Accessible.ignored: root.state!="connected" || !root.enabled
- }
- }
-
- // account name
- TextMetrics {
- id: accountMetrics
- font : accountName.font
- elide: Qt.ElideMiddle
- elideWidth: (
- statusMark.anchors.leftMargin
- - toggleIcon.anchors.leftMargin
- )
- text: account
- }
- Text {
- id: accountName
- anchors {
- verticalCenter : parent.verticalCenter
- left : toggleIcon.left
- leftMargin : Style.main.leftMargin
- }
- color: Style.main.text
- font {
- pointSize : (Style.main.fontSize+2*Style.px) * Style.pt
- }
- text: accountMetrics.elidedText
- }
-
- // status
- ClickIconText {
- id: statusMark
- anchors {
- verticalCenter : parent.verticalCenter
- left : parent.left
- leftMargin : row_width/2
- }
- text : qsTr("connected", "status of a listed logged-in account")
- iconText : Style.fa.circle_o
- textColor : Style.main.textGreen
- enabled : false
- Accessible.ignored: true
- }
-
- // export
- ClickIconText {
- id: exportAccount
- anchors {
- verticalCenter : parent.verticalCenter
- left : parent.left
- leftMargin : 5.5*row_width/8
- }
- text : qsTr("Export All", "todo")
- iconText : Style.fa.floppy_o
- textBold : true
- textColor : Style.main.textBlue
- onClicked: {
- dialogExport.currentIndex = 0
- dialogExport.account = account
- dialogExport.address = account
- dialogExport.show()
- }
- }
-
- // logout
- ClickIconText {
- id: logoutAccount
- anchors {
- verticalCenter : parent.verticalCenter
- left : exportAccount.right
- leftMargin : root.spacingLastButtons
- }
- text : qsTr("Log out", "action to log out a connected account")
- iconText : Style.fa.power_off
- textBold : true
- textColor : Style.main.textBlue
- }
-
- // remove
- ClickIconText {
- id: deleteAccount
- anchors {
- verticalCenter : parent.verticalCenter
- left : logoutAccount.right
- leftMargin : root.spacingLastButtons
- }
- text : qsTr("Remove", "deletes an account from the account settings page")
- iconText : Style.fa.trash_o
- textColor : Style.main.text
- onClicked : {
- dialogGlobal.input=iAccount
- dialogGlobal.state="deleteUser"
- dialogGlobal.show()
- }
- }
-
-
- // functions
- function toggle_accountSettings() {
- if (root.state=="connected") {
- if (mainaccRow.state=="collapsed" ) {
- mainaccRow.state="expanded"
- } else {
- mainaccRow.state="collapsed"
- }
- }
- }
-
- states: [
- State {
- name: "collapsed"
- PropertyChanges { target : toggleIcon ; text : root.state=="connected" ? Style.fa.chevron_down : " " }
- PropertyChanges { target : accountName ; font.bold : false }
- PropertyChanges { target : mainaccRow ; color : Style.main.background }
- PropertyChanges { target : addressList ; visible : false }
- },
- State {
- name: "expanded"
- PropertyChanges { target : toggleIcon ; text : Style.fa.chevron_up }
- PropertyChanges { target : accountName ; font.bold : true }
- PropertyChanges { target : mainaccRow ; color : Style.accounts.backgroundExpanded }
- PropertyChanges { target : addressList ; visible : true }
- }
- ]
- }
-
- // List of adresses
- Column {
- id: addressList
- anchors.left : parent.left
- width: row_width
- visible: false
- property alias model : repeaterAddresses.model
-
- Repeater {
- id: repeaterAddresses
- model: ["one", "two"]
-
- Rectangle {
- id: addressRow
- anchors {
- left : parent.left
- right : parent.right
- }
- height: Style.accounts.heightAddrRow
- color: Style.accounts.backgroundExpanded
-
- // iconText level down
- Text {
- id: levelDown
- anchors {
- left : parent.left
- leftMargin : Style.accounts.leftMarginAddr
- verticalCenter : wrapAddr.verticalCenter
- }
- text : Style.fa.level_up
- font.family : Style.fontawesome.name
- color : Style.main.textDisabled
- rotation : 90
- }
-
- Rectangle {
- id: wrapAddr
- anchors {
- top : parent.top
- left : levelDown.right
- right : parent.right
- leftMargin : Style.main.leftMargin
- rightMargin : Style.main.rightMargin
- }
- height: Style.accounts.heightAddr
- border {
- width : Style.main.border
- color : Style.main.line
- }
- color: Style.accounts.backgroundAddrRow
-
- TextMetrics {
- id: addressMetrics
- font: address.font
- elideWidth: (
- wrapAddr.width
- - address.anchors.leftMargin
- - 2*exportAlias.width
- - 3*exportAlias.anchors.rightMargin
- )
- elide: Qt.ElideMiddle
- text: modelData
- }
-
- Text {
- id: address
- anchors {
- verticalCenter : parent.verticalCenter
- left: parent.left
- leftMargin: Style.main.leftMargin
- }
- font.pointSize : Style.main.fontSize * Style.pt
- color: Style.main.text
- text: addressMetrics.elidedText
- }
-
- // export
- ClickIconText {
- id: exportAlias
- anchors {
- verticalCenter: parent.verticalCenter
- right: importAlias.left
- rightMargin: Style.main.rightMargin
- }
- text: qsTr("Export", "todo")
- iconText: Style.fa.floppy_o
- textBold: true
- textColor: Style.main.textBlue
- onClicked: {
- dialogExport.account = account
- dialogExport.address = listalias[index]
- dialogExport.show()
- }
- }
-
- // import
- ClickIconText {
- id: importAlias
- anchors {
- verticalCenter: parent.verticalCenter
- right: parent.right
- rightMargin: Style.main.rightMargin
- }
- text: qsTr("Import", "todo")
- iconText: Style.fa.upload
- textBold: true
- textColor: enabled ? Style.main.textBlue : Style.main.textDisabled
- onClicked: {
- dialogImport.account = account
- dialogImport.address = listalias[index]
- dialogImport.show()
- }
- }
- }
- }
- }
- }
-
- // line
- Rectangle {
- id: line
- color: Style.accounts.line
- height: Style.accounts.heightLine
- width: root.row_width
- }
-
-
- states: [
- State {
- name: "connected"
- PropertyChanges {
- target : addressList
- model : listalias
- }
- PropertyChanges {
- target : toggleIcon
- color : Style.main.text
- }
- PropertyChanges {
- target : accountName
- color : Style.main.text
- }
- PropertyChanges {
- target : statusMark
- textColor : Style.main.textGreen
- text : qsTr("connected", "status of a listed logged-in account")
- iconText : Style.fa.circle
- }
- PropertyChanges {
- target: exportAccount
- visible: true
- }
- PropertyChanges {
- target : logoutAccount
- text : qsTr("Log out", "action to log out a connected account")
- onClicked : {
- mainaccRow.state="collapsed"
- dialogGlobal.state = "logout"
- dialogGlobal.input = root.iAccount
- dialogGlobal.show()
- dialogGlobal.confirmed()
- }
- }
- },
- State {
- name: "disconnected"
- PropertyChanges {
- target : addressList
- model : 0
- }
- PropertyChanges {
- target : toggleIcon
- color : Style.main.textDisabled
- }
- PropertyChanges {
- target : accountName
- color : Style.main.textDisabled
- }
- PropertyChanges {
- target : statusMark
- textColor : Style.main.textDisabled
- text : qsTr("disconnected", "status of a listed logged-out account")
- iconText : Style.fa.circle_o
- }
- PropertyChanges {
- target : logoutAccount
- text : qsTr("Log in", "action to log in a disconnected account")
- onClicked : {
- dialogAddUser.username = root.listalias[0]
- dialogAddUser.show()
- dialogAddUser.inputPassword.focusInput = true
- }
- }
- PropertyChanges {
- target: exportAccount
- visible: false
- }
- }
- ]
-}
diff --git a/internal/frontend/qml/ImportExportUI/Credits.qml b/internal/frontend/qml/ImportExportUI/Credits.qml
deleted file mode 100644
index c252fea7..00000000
--- a/internal/frontend/qml/ImportExportUI/Credits.qml
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// credits
-
-import QtQuick 2.8
-import ProtonUI 1.0
-import ImportExportUI 1.0
-
-Item {
- id: root
- Rectangle {
- anchors.centerIn: parent
- width: Style.main.width
- height: root.parent.height - 6*Style.dialog.titleSize
- color: "transparent"
-
- ListView {
- anchors.fill: parent
- clip: true
- model: go.credits.split(";")
-
- delegate: AccessibleText {
- anchors.horizontalCenter: parent.horizontalCenter
- text: modelData
- color: Style.main.text
- font.pointSize: Style.main.fontSize * Style.pt
- }
-
- footer: ButtonRounded {
- anchors.horizontalCenter: parent.horizontalCenter
- text: qsTr("Close", "close window")
- onClicked: dialogCredits.hide()
- }
- }
- }
-}
diff --git a/internal/frontend/qml/ImportExportUI/DateBox.qml b/internal/frontend/qml/ImportExportUI/DateBox.qml
deleted file mode 100644
index c5217c4b..00000000
--- a/internal/frontend/qml/ImportExportUI/DateBox.qml
+++ /dev/null
@@ -1,220 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// input for year / month / day
-import QtQuick 2.8
-import QtQuick.Controls 2.2
-import QtQml.Models 2.2
-import ProtonUI 1.0
-import ImportExportUI 1.0
-
-ComboBox {
- id: root
-
- property string placeholderText : "none"
- property var dropDownStyle : Style.dropDownLight
- property real radius : Style.dialog.radiusButton
- property bool below : true
-
- onDownChanged : {
- root.below = popup.y>0
- }
-
-
- font.pointSize : Style.main.fontSize * Style.pt
-
- spacing : Style.dialog.spacing
- height : Style.dialog.heightInput
- width : 10*Style.px
-
- function updateWidth() {
- // make the width according to localization ( especially for Months)
- var max = 10*Style.px
- if (root.model === undefined) return
- for (var i=-1; i=0 ? root.displayText : placeholderText
- font : root.font
- color : root.enabled ? dropDownStyle.text : dropDownStyle.inactive
- verticalAlignment : Text.AlignVCenter
- elide : Text.ElideRight
- }
-
- background: Rectangle {
- color: Style.transparent
-
- MouseArea {
- anchors.fill: parent
- onClicked: root.down ? root.popup.close() : root.popup.open()
- }
- }
-
-
- DelegateModel { // FIXME QML DelegateModel: Error creating delegate
- id: filteredData
- model: root.model
- filterOnGroup: "filtered"
- groups: DelegateModelGroup {
- id: filtered
- name: "filtered"
- includeByDefault: true
- }
- delegate: root.delegate
- }
-
- function filterItems(minIndex,maxIndex) {
- // filter
- var rowCount = filteredData.items.count
- if (rowCount<=0) return
- //console.log(" filter", root.placeholderText, rowCount, minIndex, maxIndex)
- for (var iItem = 0; iItem < rowCount; iItem++) {
- var entry = filteredData.items.get(iItem);
- entry.inFiltered = ( iItem >= minIndex && iItem <= maxIndex )
- //console.log(" inserted ", iItem, rowCount, entry.model.modelData, entry.inFiltered )
- }
- }
-
- delegate: ItemDelegate {
- id: thisItem
- width : view.width
- height : Style.dialog.heightInput
- leftPadding : root.spacing
- rightPadding : root.spacing
- topPadding : 0
- bottomPadding : 0
-
- property int index : {
- //console.log( "index: ", thisItem.DelegateModel.itemsIndex )
- return thisItem.DelegateModel.itemsIndex
- }
-
- onClicked : {
- //console.log("thisItem click", thisItem.index)
- root.currentIndex = thisItem.index
- root.activated(thisItem.index)
- root.popup.close()
- }
-
-
- contentItem: Text {
- text: modelData
- color: dropDownStyle.text
- font: root.font
- elide: Text.ElideRight
- verticalAlignment: Text.AlignVCenter
- }
-
- background: Rectangle {
- color: thisItem.hovered ? dropDownStyle.highlight : dropDownStyle.background
- Text {
- anchors{
- right: parent.right
- rightMargin: root.spacing
- verticalCenter: parent.verticalCenter
- }
- font {
- family: Style.fontawesome.name
- }
- text: root.currentIndex == thisItem.index ? Style.fa.check : ""
- color: thisItem.hovered ? dropDownStyle.text : dropDownStyle.highlight
- }
-
- Rectangle {
- anchors {
- left: parent.left
- right: parent.right
- bottom: parent.bottom
- }
- height: Style.dialog.borderInput
- color: dropDownStyle.separator
- }
- }
- }
-
- popup: Popup {
- y: root.height
- x: -background.strokeWidth
- width: root.width + 2*background.strokeWidth
- modal: true
- closePolicy: Popup.CloseOnPressOutside | Popup.CloseOnEscape
- topPadding: background.radiusTopLeft + 2*background.strokeWidth
- bottomPadding: background.radiusBottomLeft + 2*background.strokeWidth
- leftPadding: 2*background.strokeWidth
- rightPadding: 2*background.strokeWidth
-
- contentItem: ListView {
- id: view
- clip: true
- implicitHeight: winMain.height/3
- model: filteredData // if you want to slide down to position: popup.visible ? root.delegateModel : null
- currentIndex: root.currentIndex
-
- ScrollIndicator.vertical: ScrollIndicator { }
- }
-
- background: RoundedRectangle {
- radiusTopLeft : root.below ? 0 : root.radius
- radiusBottomLeft : !root.below ? 0 : root.radius
- radiusTopRight : radiusTopLeft
- radiusBottomRight : radiusBottomLeft
- fillColor : dropDownStyle.background
- }
- }
-
- Component.onCompleted: {
- //console.log(" box ", label)
- root.updateWidth()
- root.filterItems(0,model.length-1)
- }
-
- onModelChanged :{
- //console.log("model changed", root.placeholderText)
- root.updateWidth()
- root.filterItems(0,model.length-1)
- }
-}
-
diff --git a/internal/frontend/qml/ImportExportUI/DateInput.qml b/internal/frontend/qml/ImportExportUI/DateInput.qml
deleted file mode 100644
index ef44d372..00000000
--- a/internal/frontend/qml/ImportExportUI/DateInput.qml
+++ /dev/null
@@ -1,264 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// input for date
-import QtQuick 2.8
-import QtQuick.Controls 2.2
-import ProtonUI 1.0
-import ImportExportUI 1.0
-
-Rectangle {
- id: root
-
- width : row.width + (root.label == "" ? 0 : textlabel.width)
- height : row.height
- color : Style.transparent
-
- property alias label : textlabel.text
- property string metricsLabel : root.label
- property var dropDownStyle : Style.dropDownLight
-
- // dates
- property date currentDate : new Date() // default now
- property date minDate : new Date(0) // default epoch start
- property date maxDate : new Date() // default now
- property bool isMaxDateToday : false
- property int unix : Math.floor(currentDate.getTime()/1000)
-
- onMinDateChanged: {
- if (isNaN(minDate.getTime()) || minDate.getTime() > maxDate.getTime()) {
- minDate = new Date(0)
- }
- //console.log(" minDate changed:", root.label, minDate.toDateString())
- updateRange()
- }
- onMaxDateChanged: {
- if (isNaN(maxDate.getTime()) || minDate.getTime() > maxDate.getTime()) {
- maxDate = new Date()
- }
- //console.log(" maxDate changed:", root.label, maxDate.toDateString())
- updateRange()
- }
-
- RoundedRectangle {
- id: background
- anchors.fill : row
- strokeColor : dropDownStyle.line
- strokeWidth : Style.dialog.borderInput
- fillColor : dropDownStyle.background
- radiusTopLeft : row.children[0].down && !row.children[0].below ? 0 : Style.dialog.radiusButton
- radiusBottomLeft : row.children[0].down && row.children[0].below ? 0 : Style.dialog.radiusButton
- radiusTopRight : row.children[row.children.length-1].down && !row.children[row.children.length-1].below ? 0 : Style.dialog.radiusButton
- radiusBottomRight : row.children[row.children.length-1].down && row.children[row.children.length-1].below ? 0 : Style.dialog.radiusButton
- }
-
- TextMetrics {
- id: textMetrics
- text: root.metricsLabel+"M"
- font: textlabel.font
- }
-
- Text {
- id: textlabel
- anchors {
- left : root.left
- verticalCenter : root.verticalCenter
- }
- font {
- pointSize: Style.dialog.fontSize * Style.pt
- bold: dropDownStyle.labelBold
- }
- color: dropDownStyle.text
- width: textMetrics.width
- verticalAlignment: Text.AlignVCenter
- }
-
- Row {
- id: row
-
- anchors {
- left : root.label=="" ? root.left : textlabel.right
- bottom : root.bottom
- }
- padding : Style.dialog.borderInput
-
- DateBox {
- id: monthInput
- placeholderText: qsTr("Month")
- enabled: !allDates
- model: gui.allMonths
- onActivated: updateRange()
- anchors.verticalCenter: parent.verticalCenter
- dropDownStyle: root.dropDownStyle
- onDownChanged: {
- if (root.isMaxDateToday){
- root.maxDate = new Date()
- }
- }
- }
-
- Rectangle {
- width: Style.dialog.borderInput
- height: monthInput.height
- color: dropDownStyle.line
- anchors.verticalCenter: parent.verticalCenter
- }
-
- DateBox {
- id: dayInput
- placeholderText: qsTr("Day")
- enabled: !allDates
- model: gui.allDays
- onActivated: updateRange()
- anchors.verticalCenter: parent.verticalCenter
- dropDownStyle: root.dropDownStyle
- onDownChanged: {
- if (root.isMaxDateToday){
- root.maxDate = new Date()
- }
- }
- }
-
- Rectangle {
- width: Style.dialog.borderInput
- height: monthInput.height
- color: dropDownStyle.line
- }
-
- DateBox {
- id: yearInput
- placeholderText: qsTr("Year")
- enabled: !allDates
- model: gui.allYears
- onActivated: updateRange()
- anchors.verticalCenter: parent.verticalCenter
- dropDownStyle: root.dropDownStyle
- onDownChanged: {
- if (root.isMaxDateToday){
- root.maxDate = new Date()
- }
- }
- }
- }
-
-
- function setDate(d) {
- //console.trace()
- //console.log( " setDate ", label, d)
- if (isNaN(d = parseInt(d))) return
- var newUnix = Math.min(maxDate.getTime(), d*1000) // seconds to ms
- newUnix = Math.max(minDate.getTime(), newUnix)
- root.updateRange(new Date(newUnix))
- //console.log( " set ", currentDate.getTime())
- }
-
-
- function updateRange(curr) {
- if (curr === undefined || isNaN(curr.getTime())) curr = root.getCurrentDate()
- //console.log( " update", label, curr, curr.getTime())
- //console.trace()
- if (isNaN(curr.getTime())) return // shouldn't happen
- // full system date range
- var firstYear = parseInt(gui.allYears[0])
- var firstDay = parseInt(gui.allDays[0])
- if ( isNaN(firstYear) || isNaN(firstDay) ) return
- // get minimal and maximal available year, month, day
- // NOTE: The order is important!!!
- var minYear = minDate.getFullYear()
- var maxYear = maxDate.getFullYear()
- var minMonth = (curr.getFullYear() == minYear ? minDate.getMonth() : 0 )
- var maxMonth = (curr.getFullYear() == maxYear ? maxDate.getMonth() : 11 )
- var minDay = (
- curr.getFullYear() == minYear &&
- curr.getMonth() == minMonth ?
- minDate.getDate() : firstDay
- )
- var maxDay = (
- curr.getFullYear() == maxYear &&
- curr.getMonth() == maxMonth ?
- maxDate.getDate() : gui.daysInMonth(curr.getFullYear(), curr.getMonth()+1)
- )
-
- //console.log("update ranges: ", root.label, minYear, maxYear, minMonth+1, maxMonth+1, minDay, maxDay)
- //console.log("update indexes: ", root.label, firstYear-minYear, firstYear-maxYear, minMonth, maxMonth, minDay-firstDay, maxDay-firstDay)
-
-
- yearInput.filterItems(firstYear-maxYear, firstYear-minYear)
- monthInput.filterItems(minMonth,maxMonth) // getMonth() is index not a month (i.e. Jan==0)
- dayInput.filterItems(minDay-1,maxDay-1)
-
- // keep ordering from model not from filter
- yearInput .currentIndex = firstYear - curr.getFullYear()
- monthInput .currentIndex = curr.getMonth() // getMonth() is index not a month (i.e. Jan==0)
- dayInput .currentIndex = curr.getDate()-firstDay
-
- /*
- console.log(
- "update current indexes: ", root.label,
- curr.getFullYear() , '->' , yearInput.currentIndex ,
- gui.allMonths[curr.getMonth()] , '->' , monthInput.currentIndex ,
- curr.getDate() , '->' , dayInput.currentIndex
- )
- */
-
- // test if current date changed
- if (
- yearInput.currentText == root.currentDate.getFullYear() &&
- monthInput.currentText == root.currentDate.toLocaleString(gui.locale, "MMM") &&
- dayInput.currentText == gui.prependZeros(root.currentDate.getDate(),2)
- ) {
- //console.log(" currentDate NOT changed", label, root.currentDate.toDateString())
- return
- }
-
- root.currentDate = root.getCurrentDate()
- // console.log(" currentDate changed", label, root.currentDate.toDateString())
- }
-
- // get current date from selected
- function getCurrentDate() {
- if (isNaN(root.currentDate.getTime())) { // wrong current ?
- console.log("!WARNING! Wrong current date format", root.currentDate)
- root.currentDate = new Date(0)
- }
- var currentString = ""
- var currentUnix = root.currentDate.getTime()
- if (
- yearInput.currentText != "" &&
- yearInput.currentText != yearInput.placeholderText &&
- monthInput.currentText != "" &&
- monthInput.currentText != monthInput.placeholderText
- ) {
- var day = gui.daysInMonth(yearInput.currentText, monthInput.currentText)
- if (!isNaN(parseInt(dayInput.currentText))) {
- day = Math.min(day, parseInt(dayInput.currentText))
- }
- var month = gui.allMonths.indexOf(monthInput.currentText)
- var year = parseInt(yearInput.currentText)
- var pickedDate = new Date(year, month, day)
- // Compensate automatic DST in windows
- if (pickedDate.getDate() != day) {
- pickedDate.setTime(pickedDate.getTime() + 60*60*1000) // add hour
- }
- currentUnix = pickedDate.getTime()
- }
- return new Date(Math.max(
- minDate.getTime(),
- Math.min(maxDate.getTime(), currentUnix)
- ))
- }
-}
diff --git a/internal/frontend/qml/ImportExportUI/DateRange.qml b/internal/frontend/qml/ImportExportUI/DateRange.qml
deleted file mode 100644
index 53e417e8..00000000
--- a/internal/frontend/qml/ImportExportUI/DateRange.qml
+++ /dev/null
@@ -1,123 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// input for date range
-import QtQuick 2.8
-import QtQuick.Controls 2.2
-import ProtonUI 1.0
-import ImportExportUI 1.0
-
-
-Column {
- id: dateRange
-
- property var structure : transferRules
- property string sourceID : "-1"
-
- property alias allDates : allDatesBox.checked
- property alias inputDateFrom : inputDateFrom
- property alias inputDateTo : inputDateTo
-
- function getRange() {common.getRange()}
- function setRangeFromTo(from, to) {common.setRangeFromTo(from, to)}
- function applyRange() {common.applyRange()}
-
- property var dropDownStyle : Style.dropDownLight
- property var isDark : dropDownStyle.background == Style.dropDownDark.background
-
- spacing: Style.dialog.spacing
-
- DateRangeFunctions {id:common}
-
- DateInput {
- id: inputDateFrom
- label: qsTr("From:")
- currentDate: gui.netBday
- maxDate: inputDateTo.currentDate
- dropDownStyle: dateRange.dropDownStyle
- }
-
- Rectangle {
- width: inputDateTo.width
- height: Style.dialog.borderInput / 2
- color: isDark ? dropDownStyle.separator : Style.transparent
- }
-
- DateInput {
- id: inputDateTo
- label: qsTr("To:")
- metricsLabel: inputDateFrom.label
- currentDate: new Date() // now
- minDate: inputDateFrom.currentDate
- isMaxDateToday: true
- dropDownStyle: dateRange.dropDownStyle
- }
-
- Rectangle {
- width: inputDateTo.width
- height: Style.dialog.borderInput
- color: isDark ? dropDownStyle.separator : Style.transparent
- }
-
- CheckBoxLabel {
- id: allDatesBox
- text : qsTr("All dates")
- anchors.right : inputDateTo.right
- checkedSymbol : Style.fa.toggle_on
- uncheckedSymbol : Style.fa.toggle_off
- uncheckedColor : Style.main.textDisabled
- textColor : dropDownStyle.text
- symbolPointSize : Style.dialog.iconSize * Style.pt * 1.1
- spacing : Style.dialog.spacing*2
-
- TextMetrics {
- id: metrics
- text: allDatesBox.checkedSymbol
- font {
- family: Style.fontawesome.name
- pointSize: allDatesBox.symbolPointSize
- }
- }
-
- Rectangle {
- color: allDatesBox.checked ? dotBackground.color : Style.exporting.sliderBackground
- width: metrics.width*0.9
- height: metrics.height*0.6
- radius: height/2
- z: -1
-
- anchors {
- left: allDatesBox.left
- verticalCenter: allDatesBox.verticalCenter
- leftMargin: 0.05 * metrics.width
- }
-
- Rectangle {
- id: dotBackground
- color : Style.exporting.background
- height : parent.height
- width : height
- radius : height/2
- anchors {
- left : parent.left
- verticalCenter : parent.verticalCenter
- }
-
- }
- }
- }
-}
diff --git a/internal/frontend/qml/ImportExportUI/DateRangeFunctions.qml b/internal/frontend/qml/ImportExportUI/DateRangeFunctions.qml
deleted file mode 100644
index 3b5c4813..00000000
--- a/internal/frontend/qml/ImportExportUI/DateRangeFunctions.qml
+++ /dev/null
@@ -1,81 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// input for date range
-import QtQuick 2.8
-import QtQuick.Controls 2.2
-import ProtonUI 1.0
-import ImportExportUI 1.0
-
-Item {
- id: root
- /*
- NOTE: need to be in obejct with
- id: dateRange
-
- property var structure : structureExternal
- property string sourceID : structureExternal.getID ( -1 )
-
- property alias allDates : allDatesBox.checked
- property alias inputDateFrom : inputDateFrom
- property alias inputDateTo : inputDateTo
-
- function getRange() {common.getRange()}
- function applyRange() {common.applyRange()}
- */
-
- function resetRange() {
- inputDateFrom.setDate(gui.netBday.getTime())
- inputDateTo.setDate((new Date()).getTime())
- }
-
- function setRangeFromTo(folderFrom, folderTo){ // unix time in seconds
- if ( folderFrom == 0 && folderTo ==0 ) {
- dateRange.allDates = true
- } else {
- dateRange.allDates = false
- inputDateFrom.setDate(folderFrom)
- inputDateTo.setDate(folderTo)
- }
- }
-
- function getRange(){ // unix time in seconds
- //console.log(" ==== GET RANGE === ")
- //console.trace()
- var folderFrom = dateRange.structure.globalFromDate
- var folderTo = dateRange.structure.globalToDate
-
- root.setRangeFromTo(folderFrom, folderTo)
- }
-
- function applyRange(){ // unix time is seconds
- if (dateRange.allDates) structure.setFromToDate(dateRange.sourceID, 0, 0)
- else {
- var endOfDay = new Date(inputDateTo.unix*1000)
- endOfDay.setHours(23,59,59,999)
- var endOfDayUnix = parseInt(endOfDay.getTime()/1000)
- structure.setFromToDate(dateRange.sourceID, inputDateFrom.unix, endOfDayUnix)
- }
- }
-
- Component.onCompleted: {
- inputDateFrom.updateRange(gui.netBday)
- inputDateTo.updateRange(new Date())
- //getRange()
- }
-}
-
diff --git a/internal/frontend/qml/ImportExportUI/DateRangeMenu.qml b/internal/frontend/qml/ImportExportUI/DateRangeMenu.qml
deleted file mode 100644
index 34d307d0..00000000
--- a/internal/frontend/qml/ImportExportUI/DateRangeMenu.qml
+++ /dev/null
@@ -1,163 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// List of import folder and their target
-import QtQuick 2.8
-import QtQuick.Controls 2.2
-import ProtonUI 1.0
-import ImportExportUI 1.0
-
-
-Rectangle {
- id:root
-
- width : icon.width + indicator.width + 3*padding
- height : icon.height + 3*padding
-
- property real padding : Style.dialog.spacing
- property bool down : popup.visible
-
- property var structure : transferRules
- property string sourceID : ""
- property int sourceFromDate : 0
- property int sourceToDate : 0
-
- color: Style.transparent
-
- RoundedRectangle {
- anchors.fill: parent
- radiusTopLeft: root.down ? 0 : Style.dialog.radiusButton
- fillColor: root.down ? Style.main.textBlue : Style.transparent
- }
-
- Text {
- id: icon
- text: Style.fa.calendar_o
- anchors {
- left : parent.left
- leftMargin : root.padding
- verticalCenter : parent.verticalCenter
- }
-
- color: root.enabled ? (
- root.down ? Style.main.background : Style.main.text
- ) : Style.main.textDisabled
-
- font.family : Style.fontawesome.name
-
- Text {
- anchors {
- verticalCenter: parent.bottom
- horizontalCenter: parent.right
- }
-
- color : !root.down && root.enabled ? Style.main.textRed : icon.color
- text : Style.fa.exclamation_circle
- visible : !dateRangeInput.allDates
- font.pointSize : root.padding * Style.pt * 1.5
- font.family : Style.fontawesome.name
- }
- }
-
-
- Text {
- id: indicator
- anchors {
- right : parent.right
- rightMargin : root.padding
- verticalCenter : parent.verticalCenter
- }
-
- text : root.down ? Style.fa.chevron_up : Style.fa.chevron_down
- color : !root.down && root.enabled ? Style.main.textBlue : icon.color
- font.family : Style.fontawesome.name
- }
-
- MouseArea {
- anchors.fill: root
- onClicked: {
- popup.open()
- }
- }
-
- Popup {
- id: popup
-
- x : -width
- modal : true
- clip : true
-
- topPadding : 0
-
- background: RoundedRectangle {
- fillColor : Style.bubble.paneBackground
- strokeColor : fillColor
- radiusTopRight: 0
-
- RoundedRectangle {
- anchors {
- left: parent.left
- right: parent.right
- top: parent.top
- }
- height: Style.dialog.heightInput
- fillColor: Style.dropDownDark.highlight
- strokeColor: fillColor
- radiusTopRight: 0
- radiusBottomLeft: 0
- radiusBottomRight: 0
- }
- }
-
- contentItem : Column {
- spacing: Style.dialog.spacing
-
- Text {
- anchors {
- left: parent.left
- }
-
- text : qsTr("Import date range")
- font.bold : Style.dropDownDark.labelBold
- color : Style.dropDownDark.text
- height : Style.dialog.heightInput
- verticalAlignment : Text.AlignVCenter
- }
-
- DateRange {
- id: dateRangeInput
- allDates: true
- structure: root.structure
- sourceID: root.sourceID
- dropDownStyle: Style.dropDownDark
- }
- }
-
- onAboutToShow : updateRange()
- onAboutToHide : dateRangeInput.applyRange()
- }
-
- function updateRange() {
- dateRangeInput.setRangeFromTo(root.sourceFromDate, root.sourceToDate)
- }
-
- Connections {
- target:root
- onSourceFromDateChanged: root.updateRange()
- onSourceToDateChanged: root.updateRange()
- }
-}
diff --git a/internal/frontend/qml/ImportExportUI/DialogExport.qml b/internal/frontend/qml/ImportExportUI/DialogExport.qml
deleted file mode 100644
index 16a48805..00000000
--- a/internal/frontend/qml/ImportExportUI/DialogExport.qml
+++ /dev/null
@@ -1,459 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// Export dialog
-import QtQuick 2.8
-import QtQuick.Controls 2.2
-import ProtonUI 1.0
-import ImportExportUI 1.0
-
-// TODO
-// - make ErrorDialog module
-// - map decision to error code : ask (default), skip ()
-// - what happens when import fails ? heuristic to find mail where to start from
-
-Dialog {
- id: root
-
- enum Page {
- LoadingStructure = 0, Options, Progress
- }
-
- title : set_title()
-
- property string account
- property string address
- property alias finish: finish
-
- property string msgClearUnfished: qsTr ("Remove already exported files.")
-
- isDialogBusy : true // currentIndex == 0 || currentIndex == 3
-
- signal cancel()
- signal okay()
-
-
- Rectangle { // 0
- id: dialogLoading
- width: root.width
- height: root.height
- color: Style.transparent
-
- Text {
- anchors.centerIn : dialogLoading
- font.pointSize: Style.dialog.titleSize * Style.pt
- color: Style.dialog.text
- horizontalAlignment: Text.AlignHCenter
- text: qsTr("Loading folders and labels for", "todo") +"\n" + address
- }
- }
-
- Rectangle { // 1
- id: dialogInput
- width: root.width
- height: root.height
- color: Style.transparent
-
- Row {
- id: inputRow
- anchors {
- topMargin : root.titleHeight
- top : parent.top
- horizontalCenter : parent.horizontalCenter
- }
- spacing: 3*Style.main.leftMargin
- property real columnWidth : (root.width - Style.main.leftMargin - inputRow.spacing - Style.main.rightMargin) / 2
- property real columnHeight : root.height - root.titleHeight - Style.main.leftMargin
-
-
- ExportStructure {
- id: sourceFoldersInput
- width : inputRow.columnWidth
- height : inputRow.columnHeight
- title : qsTr("From: %1", "todo").arg(address)
- }
-
- Column {
- spacing: (inputRow.columnHeight - dateRangeInput.height - outputFormatInput.height - outputPathInput.height - buttonRow.height - infotipEncrypted.height) / 4
-
- DateRange{
- id: dateRangeInput
- }
-
- OutputFormat {
- id: outputFormatInput
- }
-
- Row {
- spacing: Style.dialog.spacing
- CheckBoxLabel {
- id: exportEncrypted
- text: qsTr("Export emails that cannot be decrypted as ciphertext")
- anchors {
- bottom: parent.bottom
- bottomMargin: Style.dialog.fontSize/1.8
- }
- }
-
- InfoToolTip {
- id: infotipEncrypted
- anchors {
- verticalCenter: exportEncrypted.verticalCenter
- }
- info: qsTr("Checking this option will export all emails that cannot be decrypted in ciphertext. If this option is not checked, these emails will not be exported", "todo")
- }
- }
-
- FileAndFolderSelect {
- id: outputPathInput
- title: qsTr("Select location of export:", "todo")
- width : inputRow.columnWidth // stretch folder input
- }
-
- Row {
- id: buttonRow
- anchors.right : parent.right
- spacing : Style.dialog.rightMargin
-
- ButtonRounded {
- id:buttonCancel
- fa_icon: Style.fa.times
- text: qsTr("Cancel")
- color_main: Style.main.textBlue
- onClicked : root.cancel()
- }
-
- ButtonRounded {
- id: buttonNext
- fa_icon: Style.fa.check
- text: qsTr("Export","todo")
- enabled: transferRules != 0
- color_main: Style.dialog.background
- color_minor: enabled ? Style.dialog.textBlue : Style.main.textDisabled
- isOpaque: true
- onClicked : root.okay()
- }
- }
- }
- }
- }
-
- Rectangle { // 2
- id: progressStatus
- width: root.width
- height: root.height
- color: "transparent"
-
- Row {
- anchors {
- bottom: progressbarExport.top
- bottomMargin: Style.dialog.heightSeparator
- left: progressbarExport.left
- }
- spacing: Style.main.rightMargin
- AccessibleText {
- id: statusLabel
- text : qsTr("Status:")
- font.pointSize: Style.main.iconSize * Style.pt
- color : Style.main.text
- }
- AccessibleText {
- anchors.baseline: statusLabel.baseline
- text : {
- if (progressbarExport.isFinished) return qsTr("finished")
- if (go.progressDescription == "") return qsTr("exporting")
- return go.progressDescription
- }
- elide: Text.ElideMiddle
- width: progressbarExport.width - parent.spacing - statusLabel.width
- font.pointSize: Style.dialog.textSize * Style.pt
- color : Style.main.textDisabled
- }
- }
-
- ProgressBar {
- id: progressbarExport
- implicitWidth : 2*progressStatus.width/3
- implicitHeight : Style.exporting.rowHeight
- value: go.progress
- property int current: go.total * go.progress
- property bool isFinished: finishedPartBar.width == progressbarExport.width
- anchors {
- centerIn: parent
- }
- background: Rectangle {
- radius : Style.exporting.boxRadius
- color : Style.exporting.progressBackground
- }
- contentItem: Item {
- Rectangle {
- id: finishedPartBar
- width : parent.width * progressbarExport.visualPosition
- height : parent.height
- radius : Style.exporting.boxRadius
- gradient : Gradient {
- GradientStop { position: 0.00; color: Qt.lighter(Style.exporting.progressStatus,1.1) }
- GradientStop { position: 0.66; color: Style.exporting.progressStatus }
- GradientStop { position: 1.00; color: Qt.darker(Style.exporting.progressStatus,1.1) }
- }
-
- Behavior on width {
- NumberAnimation { duration:800; easing.type: Easing.InOutQuad }
- }
- }
- Text {
- anchors.centerIn: parent
- text: {
- if (progressbarExport.isFinished) {
- if (go.progressDescription=="") return qsTr("Export finished","todo")
- else return qsTr("Export failed: %1").arg(go.progressDescription)
- }
- if (
- go.progressDescription == gui.enums.progressInit ||
- (go.progress==0 && go.description=="")
- ) {
- if (go.total>1) return qsTr("Estimating the total number of messages (%1)","todo").arg(go.total)
- else return qsTr("Estimating the total number of messages","todo")
- }
- var msg = qsTr("Exporting message %1 of %2 (%3%)","todo")
- if (pauseButton.paused) msg = qsTr("Exporting paused at message %1 of %2 (%3%)","todo")
- return msg.arg(progressbarExport.current).arg(go.total).arg(Math.floor(go.progress*100))
- }
- color: Style.main.background
- font {
- pointSize: Style.dialog.fontSize * Style.pt
- }
- }
- }
- }
-
- Row {
- anchors {
- top: progressbarExport.bottom
- topMargin : Style.dialog.heightSeparator
- horizontalCenter: parent.horizontalCenter
- }
- spacing: Style.dialog.rightMargin
-
- ButtonRounded {
- id: pauseButton
- property bool paused : false
- fa_icon : paused ? Style.fa.play : Style.fa.pause
- text : paused ? qsTr("Resume") : qsTr("Pause")
- color_main : Style.dialog.textBlue
- onClicked : {
- if (paused) {
- if (winMain.updateState == gui.enums.statusNoInternet) {
- go.notifyError(gui.enums.errNoInternet)
- return
- }
- go.resumeProcess()
- } else {
- go.pauseProcess()
- }
- paused = !paused
- pauseButton.focus=false
- }
- visible : !progressbarExport.isFinished
- }
-
- ButtonRounded {
- fa_icon : Style.fa.times
- text : qsTr("Cancel")
- color_main : Style.dialog.textBlue
- visible : !progressbarExport.isFinished
- onClicked : root.ask_cancel_progress()
- }
-
- ButtonRounded {
- id: finish
- fa_icon : Style.fa.check
- text : qsTr("Okay","todo")
- color_main : Style.dialog.background
- color_minor : Style.dialog.textBlue
- isOpaque : true
- visible : progressbarExport.isFinished
- onClicked : root.okay()
- }
- }
-
- ClickIconText {
- id: buttonHelp
- anchors {
- right : parent.right
- bottom : parent.bottom
- rightMargin : Style.main.rightMargin
- bottomMargin : Style.main.rightMargin
- }
- textColor : Style.main.textDisabled
- iconText : Style.fa.question_circle
- text : qsTr("Help", "directs the user to the online user guide")
- textBold : true
- onClicked : Qt.openUrlExternally("https://protonmail.com/support/categories/import-export/")
- }
- }
-
- PopupMessage {
- id: errorPopup
- width: root.width
- height: root.height
- }
-
- function check_inputs() {
- if (currentIndex == 1) {
- // at least one email to export
- if (transferRules.rowCount() == 0){
- errorPopup.show(qsTr("No emails found to export. Please try another address.", "todo"))
- return false
- }
- // at least one source selected
- /*
- if (!transferRules.atLeastOneSelected) {
- errorPopup.show(qsTr("Please select at least one item to export.", "todo"))
- return false
- }
- */
- // check path
- var folderCheck = go.checkPathStatus(outputPathInput.path)
- switch (folderCheck) {
- case gui.enums.pathEmptyPath:
- errorPopup.show(qsTr("Missing export path. Please select an output folder."))
- break;
- case gui.enums.pathWrongPath:
- errorPopup.show(qsTr("Folder '%1' not found. Please select an output folder.").arg(outputPathInput.path))
- break;
- case gui.enums.pathOK | gui.enums.pathNotADir:
- errorPopup.show(qsTr("File '%1' is not a folder. Please select an output folder.").arg(outputPathInput.path))
- break;
- case gui.enums.pathWrongPermissions:
- errorPopup.show(qsTr("Cannot access folder '%1'. Please check folder permissions.").arg(outputPathInput.path))
- break;
- }
- if (
- (folderCheck&gui.enums.pathOK)==0 ||
- (folderCheck&gui.enums.pathNotADir)==gui.enums.pathNotADir
- ) return false
- if (winMain.updateState == gui.enums.statusNoInternet) {
- errorPopup.show(qsTr("Please check your internet connection."))
- return false
- }
- }
- return true
- }
-
- function set_title() {
- switch(root.currentIndex){
- case 1 : return qsTr("Select what you'd like to export:")
- default: return ""
- }
- }
-
- function clear_status() {
- go.progress=0.0
- go.total=0.0
- go.progressDescription=gui.enums.progressInit
- }
-
- function ask_cancel_progress(){
- errorPopup.buttonYes.visible = true
- errorPopup.buttonNo.visible = true
- errorPopup.buttonOkay.visible = false
- errorPopup.show ("Are you sure you want to cancel this export?")
- }
-
-
- onCancel : {
- switch (root.currentIndex) {
- case 0 :
- case 1 : root.hide(); break;
- case 2 : // progress bar
- go.cancelProcess();
- // no break
- default:
- root.clear_status()
- root.currentIndex=1
- }
- }
-
- onOkay : {
- var isOK = check_inputs()
- if (!isOK) return
- timer.interval= currentIndex==1 ? 1 : 300
- switch (root.currentIndex) {
- case 2: // progress
- root.clear_status()
- root.hide()
- break
- case 0: // loading structure
- dateRangeInput.getRange()
- //no break
- default:
- incrementCurrentIndex()
- timer.start()
- }
- }
-
- onShow: {
- if (winMain.updateState==gui.enums.statusNoInternet) {
- if (winMain.updateState==gui.enums.statusNoInternet) {
- go.notifyError(gui.enums.errNoInternet)
- root.hide()
- return
- }
- }
-
- root.clear_status()
- root.currentIndex=0
- timer.interval = 300
- timer.start()
- dateRangeInput.allDates = true
- }
-
- Connections {
- target: timer
- onTriggered : {
- switch (currentIndex) {
- case 0:
- go.loadStructureForExport(root.account, root.address)
- sourceFoldersInput.hasItems = (transferRules.rowCount() > 0)
- break
- case 2:
- dateRangeInput.applyRange()
- go.startExport(
- outputPathInput.path,
- root.address,
- outputFormatInput.checkedText,
- exportEncrypted.checked
- )
- break
- }
- }
- }
-
- Connections {
- target: errorPopup
-
- onClickedOkay : errorPopup.hide()
- onClickedYes : {
- root.cancel()
- errorPopup.hide()
- }
- onClickedNo : {
- errorPopup.hide()
- }
- }
-}
diff --git a/internal/frontend/qml/ImportExportUI/DialogImport.qml b/internal/frontend/qml/ImportExportUI/DialogImport.qml
deleted file mode 100644
index 0a862039..00000000
--- a/internal/frontend/qml/ImportExportUI/DialogImport.qml
+++ /dev/null
@@ -1,1043 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// Export dialog
-import QtQuick 2.8
-import QtQuick.Controls 2.2
-import QtQuick.Layouts 1.3
-import QtQuick.Dialogs 1.0
-import ProtonUI 1.0
-import ImportExportUI 1.0
-
-Dialog {
- id: root
-
- enum Page {
- SelectSourceType=0, ImapSource, LoadingStructure, SourceToTarget, Progress, Report
- }
-
- title: "" // qsTr("Importing from: %1", "todo").arg(address)
-
- isDialogBusy: currentIndex==3 || currentIndex==4
-
- property string account
- property string address
- property string inputPath : ""
- property bool isFromFile : inputEmail.text == "" && root.inputPath != ""
- property bool isFromIMAP : inputEmail.text != ""
- property bool paused : false
-
- property string msgDontShowAgain : qsTr("Do not show this message again")
-
-
- signal cancel()
- signal okay()
-
-
- Rectangle { // SelectSourceType
- id: sourceType
- width: parent.width
- height: parent.height
- color: "transparent"
-
- Text {
- anchors {
- horizontalCenter : parent.horizontalCenter
- top : parent.top
- topMargin : Style.dialog.titleSize
- }
-
- font.pointSize: Style.dialog.titleSize * Style.pt
- color: Style.dialog.text
- text: qsTr("Please select the source of the emails that you would like to import:")
- }
-
- Row {
- anchors {
- centerIn: parent
- }
-
- ImportSourceButton {
- id: imapButton
- width: winMain.width/2
- iconText: "envelope_open"
- text: qsTr("Import from account")
- onClicked: root.incrementCurrentIndex()
- }
-
- ImportSourceButton {
- id: fileButton
- width: winMain.width/2
- iconText: "folder_open"
- text: qsTr("Import local files")
- onClicked: { pathDialog.visible = true }
- anchors.bottom: imapButton.bottom
- }
- }
-
- FileDialog {
- id: pathDialog
- title: "Select local folder to import"
- folder: shortcuts.home
- onAccepted: {
- sanitizePath(pathDialog.fileUrl.toString())
- root.okay()
- }
- selectFolder: true
- }
- }
-
- Rectangle { // ImapSource
- id: imapSource
-
- Text {
- id: imapSourceTitle
- anchors {
- top : parent.top
- topMargin: imapSourceTitle.height / 2
- horizontalCenter : parent.horizontalCenter
- }
-
- font.pointSize: Style.dialog.titleSize * Style.pt
- color: Style.dialog.text
- text: qsTr("Sign in to your Account")
- }
-
- Rectangle { // line
- id: titleLine
- anchors {
- top: imapSourceTitle.bottom
- topMargin: imapSourceTitle.height / 2
- horizontalCenter : parent.horizontalCenter
- }
- width: imapSourceContent.width
- height: Style.main.heightLine
- color: Style.main.line
- }
-
- Rectangle {
- id: imapSourceContent
- anchors {
- top: titleLine.bottom
- topMargin: imapSourceTitle.height / 2
- bottom: buttonRow.top
- }
- width: winMain.width
- color: Style.dialog.background
-
- Text {
- id: note
- anchors {
- bottom: wrapper.top
- bottomMargin: imapSourceTitle.height / 2
- horizontalCenter : parent.horizontalCenter
- }
- text: qsTr(
- "Many email providers (Gmail, Yahoo, etc.) will require you to allow remote sign-on in order to perform import through IMAP. See this article for details about how to do this with your email account.",
- "Note added at IMAP credential page."
- ).arg("https://protonmail.com/support/knowledge-base/allowing-imap-access-and-entering-imap-details/")
- font {
- pointSize: Style.dialog.fontSize * Style.pt
- }
- color: Style.dialog.text
- linkColor: Style.dialog.textBlue
- wrapMode: Text.WordWrap
- textFormat: Text.StyledText
- horizontalAlignment: Text.AlignHCenter
-
- width: parent.width * 0.618
- onLinkActivated: Qt.openUrlExternally(link)
- }
-
- Rectangle {
- id: wrapper
- anchors.centerIn: parent
- width: firstRow.width
- height: firstRow.height + secondRow.height + secondRow.anchors.topMargin
- color: Style.transparent
- Row {
- id: firstRow
- spacing: imapSourceTitle.height
-
- InputField {
- id: inputEmail
- iconText: Style.fa.user_circle
- label: qsTr("Email", "todo") + ":"
- onEditingFinished: {
- root.guessEmailProvider()
- }
- onAccepted: if (root.check_inputs()) root.okay()
- anchors.horizontalCenter: undefined
- }
-
- InputField {
- id: inputPassword
- label : qsTr("Password:")
- iconText : Style.fa.lock
- isPassword: true
- onAccepted: if (root.check_inputs()) root.okay()
- anchors.horizontalCenter: undefined
- }
- }
-
- Row {
- id: secondRow
- spacing: imapSourceTitle.height
- anchors {
- top: firstRow.bottom
- topMargin: 2*imapSourceTitle.height
- }
-
- InputField {
- id: inputServer
- iconText: Style.fa.server
- label: qsTr("Server address", "todo") + ":"
- onAccepted: if (root.check_inputs()) root.okay()
- anchors.horizontalCenter: undefined
- }
-
- InputField {
- id: inputPort
- iconText: Style.fa.hashtag
- label: qsTr("Port:")
- onAccepted: if (root.check_inputs()) root.okay()
- anchors.horizontalCenter: undefined
- }
- }
- }
- }
-
- Row { // Buttons
- id:buttonRow
- anchors {
- right : parent.right
- bottom : parent.bottom
- rightMargin : Style.dialog.rightMargin
- bottomMargin : Style.dialog.bottomMargin
- }
- spacing: Style.main.leftMargin
-
- ButtonRounded {
- fa_icon : Style.fa.times
- text : qsTr("Cancel", "todo")
- color_main : Style.dialog.textBlue
- onClicked : root.cancel()
- }
-
- ButtonRounded {
- fa_icon : Style.fa.check
- text : qsTr("Next", "todo")
- color_main : Style.dialog.background
- color_minor : Style.dialog.textBlue
- isOpaque : true
- onClicked : root.okay()
- }
- }
- }
-
- Rectangle { // LoadingStructure
- id: loadingStructures
- color : Style.dialog.background
- width : parent.width
- height : parent.height
-
- Text {
- anchors {
- verticalCenter : parent.verticalCenter
- horizontalCenter : parent.horizontalCenter
- topMargin : Style.dialog.titleSize
- }
- font.pointSize: Style.dialog.titleSize * Style.pt
- color: Style.dialog.text
- text: root.isFromFile ? qsTr("Loading folder structures, please wait...") : qsTr("Loading structure of IMAP account, please wait...")
- }
- }
-
- Rectangle { // SourceToTarget
- id: dialogStructure
- width : parent.width
- height : parent.height
-
- // Import instructions
- ImportStructure {
- id: importInstructions
- anchors.bottom : masterImportSettings.top
- titleFrom : root.isFromFile ? root.inputPath : inputEmail.text
- titleTo : root.address
- }
-
- Column {
- id: masterImportSettings
- anchors {
- right : parent.right
- left : parent.left
- bottom : parent.bottom
-
- leftMargin : Style.main.leftMargin
- rightMargin : Style.main.leftMargin
- bottomMargin : Style.main.bottomMargin
- }
-
- spacing: Style.main.bottomMargin
-
- Row {
- spacing: masterImportSettings.width - labelMasterImportSettings.width - resetSourceButton.width
-
- Text {
- id: labelMasterImportSettings
- text: qsTr("Master import settings:")
-
- font {
- bold: true
- pointSize: Style.main.fontSize * Style.pt
- }
- color: Style.main.text
-
- InfoToolTip {
- anchors {
- left: parent.right
- bottom: parent.bottom
- leftMargin : Style.dialog.leftMargin
- }
- info: qsTr(
- "If master import date range is selected only emails within this range will be imported, unless it is specified differently in folder date range.",
- "Text in master import settings tooltip."
- )
- }
- }
-
- // Reset all to default
- ClickIconText {
- id: resetSourceButton
- text:qsTr("Reset all settings to default")
- iconText: Style.fa.refresh
- textColor: Style.main.textBlue
- onClicked: {
- go.resetSource()
- root.decrementCurrentIndex()
- timer.start()
- }
- }
- }
-
- Rectangle{
- id: line
- anchors {
- left : parent.left
- right : parent.right
- top : labelMasterImportSettings.bottom
-
- topMargin : Style.dialog.spacing
- }
- height : Style.main.border * 2
- color : Style.main.line
- }
-
- InlineDateRange {
- id: globalDateRange
- }
-
- // Add global label (inline)
- InlineLabelSelect {
- id: globalLabels
- }
-
- Row {
- spacing: Style.dialog.spacing
- CheckBoxLabel {
- id: importEncrypted
- text: qsTr("Import encrypted emails as they are")
- anchors {
- bottom: parent.bottom
- bottomMargin: Style.dialog.fontSize/1.8
- }
- }
-
- InfoToolTip {
- anchors {
- verticalCenter: importEncrypted.verticalCenter
- }
- info: qsTr("When this option is enabled, encrypted emails will be imported as ciphertext. Otherwise, such messages will be skipped.", "todo")
- }
- }
- }
-
- // Buttons
- Row {
- spacing: Style.dialog.spacing
- anchors {
- right: parent.right
- bottom: parent.bottom
- rightMargin: Style.main.leftMargin
- bottomMargin: Style.main.bottomMargin
- }
-
- ButtonRounded {
- id: buttonCancelThree
- fa_icon : Style.fa.times
- text : qsTr("Cancel", "todo")
- color_main : Style.dialog.textBlue
- onClicked : root.cancel()
- }
-
- ButtonRounded {
- id: buttonNextThree
- fa_icon : Style.fa.check
- text : qsTr("Import", "todo")
- color_main : Style.dialog.background
- color_minor : Style.dialog.textBlue
- isOpaque : true
- onClicked : root.okay()
- }
- }
- }
-
- Rectangle { // Progress
- id: progressStatus
- width : parent.width
- height : parent.height
- color: Style.transparent
-
- Column {
- anchors.centerIn: progressStatus
- spacing: Style.dialog.heightSeparator
-
- Row { // description
- spacing: Style.main.rightMargin
- AccessibleText {
- id: statusLabel
- text : qsTr("Status:")
- font.pointSize: Style.main.iconSize * Style.pt
- color : Style.main.text
- }
- AccessibleText {
- anchors.baseline: statusLabel.baseline
- text : go.progressDescription == "" ? qsTr("importing") : go.progressDescription
- elide: Text.ElideMiddle
- width: progressbarImport.width - parent.spacing - statusLabel.width
- font.pointSize: Style.dialog.textSize * Style.pt
- color : Style.main.textDisabled
- }
- }
-
- ProgressBar {
- id: progressbarImport
- implicitWidth : 2*progressStatus.width/3
- implicitHeight : Style.exporting.rowHeight
- value: go.progress
- property int current: go.total * go.progress
- property bool isFinished: finishedPartBar.width == progressbarImport.width
-
- background: Rectangle {
- radius : Style.exporting.boxRadius
- color : Style.exporting.progressBackground
- }
-
- contentItem: Item {
- Rectangle {
- id: finishedPartBar
- width : parent.width * progressbarImport.visualPosition
- height : parent.height
- radius : Style.exporting.boxRadius
- gradient : Gradient {
- GradientStop { position: 0.00; color: Qt.lighter(Style.exporting.progressStatus,1.1) }
- GradientStop { position: 0.66; color: Style.exporting.progressStatus }
- GradientStop { position: 1.00; color: Qt.darker(Style.exporting.progressStatus,1.1) }
- }
-
- Behavior on width {
- NumberAnimation { duration:800; easing.type: Easing.InOutQuad }
- }
- }
- Text {
- anchors.centerIn: parent
- text: {
- if (progressbarImport.isFinished) return qsTr("Import finished","todo")
- if (
- go.progressDescription == gui.enums.progressInit ||
- (go.progress == 0 && go.progressDescription=="")
- ) return qsTr("Estimating the total number of messages","todo")
- if (
- go.progressDescription == gui.enums.progressLooping
- ) return qsTr("Loading first message","todo")
- //var msg = qsTr("Importing message %1 of %2 (%3%)","todo")
- var msg = qsTr("Importing messages %1 of %2 (%3%)","todo")
- if (root.paused) msg = qsTr("Importing paused at %1 of %2 (%3%)","todo")
- return msg.arg(progressbarImport.current).arg(go.total).arg(Math.floor(go.progress*100))
- }
- color: Style.main.background
- font {
- pointSize: Style.dialog.fontSize * Style.pt
- }
- }
- }
-
- onIsFinishedChanged: { // show report
- console.log("Is finished ", progressbarImport.isFinished)
- if (progressbarImport.isFinished && root.currentIndex == DialogImport.Page.Progress) {
- root.incrementCurrentIndex()
- }
- }
- }
-
- Row {
- property int fails: go.progressFails
- visible: fails > 0
- anchors.horizontalCenter: parent.horizontalCenter
-
- Text {
- color: Style.main.textRed
- font {
- pointSize : Style.dialog.fontSize * Style.pt
- family : Style.fontawesome.name
- }
- text: Style.fa.exclamation_circle
- }
-
- Text {
- property int fails: go.progressFails
- color: Style.main.textRed
- font.pointSize: Style.main.fontSize * Style.pt
- text: " " + (
- fails == 1 ?
- qsTr("%1 message failed to be imported").arg(fails) :
- qsTr("%1 messages failed to be imported").arg(fails)
- )
- }
- }
-
- Row { // buttons
- spacing: Style.dialog.rightMargin
- anchors.horizontalCenter: parent.horizontalCenter
-
- ButtonRounded {
- id: pauseButton
- fa_icon : root.paused ? Style.fa.play : Style.fa.pause
- text : root.paused ? qsTr("Resume") : qsTr("Pause")
- color_main : Style.dialog.textBlue
- onClicked : {
- if (root.paused) {
- if (winMain.updateState == gui.enums.statusNoInternet) {
- go.notifyError(gui.enums.errNoInternet)
- return
- }
- go.resumeProcess()
- } else {
- go.pauseProcess()
- }
- root.paused = !root.paused
- pauseButton.focus=false
- }
- visible : !progressbarImport.isFinished
- }
-
- ButtonRounded {
- fa_icon : Style.fa.times
- text : qsTr("Cancel")
- color_main : Style.dialog.textBlue
- visible : !progressbarImport.isFinished
- onClicked : root.ask_cancel_progress()
- }
-
- ButtonRounded {
- id: finish
- fa_icon : Style.fa.check
- text : qsTr("Okay","todo")
- color_main : Style.dialog.background
- color_minor : Style.dialog.textBlue
- isOpaque : true
- visible : progressbarImport.isFinished
- onClicked : root.okay()
- }
- }
- }
-
- ImportReport {
- }
-
- ClickIconText {
- id: buttonHelp
- anchors {
- bottom: progressStatus.bottom
- right: progressStatus.right
- margins: Style.main.rightMargin
- }
-
- textColor : Style.main.textDisabled
- iconText : Style.fa.question_circle
- text : qsTr("Help", "directs the user to the online user guide")
- textBold : true
- onClicked : Qt.openUrlExternally("https://protonmail.com/support/categories/import-export/")
- }
- }
-
- Rectangle { // Report
- id: finalReport
- width : parent.width
- height : parent.height
- color: Style.transparent
-
- property int imported: go.total - go.progressFails
-
-
- Column {
- anchors.centerIn : finalReport
- spacing : Style.dialog.heightSeparator
-
- Row {
- anchors.horizontalCenter: parent.horizontalCenter
-
- Text {
- font {
- pointSize: Style.dialog.fontSize * Style.pt
- family: Style.fontawesome.name
- }
- color: Style.main.textGreen
- text: go.progressDescription!="" ? "" : Style.fa.check_circle
- }
-
- Text {
- text: go.progressDescription!="" ? qsTr("Import failed: %1").arg(go.progressDescription) : " " + qsTr("Import completed successfully")
- color: go.progressDescription!="" ? Style.main.textRed : Style.main.textGreen
- font.bold : true
- }
- }
-
- Text {
- text: qsTr("Import summary:
Total number of emails: %1
Imported emails: %2
Filtered out emails: %3
Errors: %4").arg(go.total).arg(go.progressImported).arg(go.progressSkipped).arg(go.progressFails)
- anchors.horizontalCenter: parent.horizontalCenter
- textFormat: Text.RichText
- horizontalAlignment: Text.AlignHCenter
- }
-
- Row {
- spacing: Style.dialog.rightMargin
- anchors.horizontalCenter: parent.horizontalCenter
-
- ButtonRounded {
- fa_icon : Style.fa.info_circle
- text : qsTr("View errors")
- color_main : Style.dialog.textBlue
- onClicked : {
- go.loadImportReports()
- reportList.show()
- }
- }
-
- ButtonRounded {
- fa_icon : Style.fa.send
- text : qsTr("Report files")
- color_main : Style.dialog.textBlue
- onClicked : {
- root.ask_send_report()
- }
- }
- }
-
- ButtonRounded {
- text : qsTr("Close")
- color_main : Style.dialog.background
- color_minor : Style.dialog.textBlue
- isOpaque : true
- anchors.horizontalCenter: parent.horizontalCenter
- onClicked: root.okay()
- }
- }
-
- ImportReport {
- id: reportList
- anchors.fill: finalReport
- }
-
- ClickIconText {
- anchors {
- bottom: finalReport.bottom
- right: finalReport.right
- margins: Style.main.rightMargin
- }
-
- textColor : Style.main.textDisabled
- iconText : Style.fa.question_circle
- text : qsTr("Help", "directs the user to the online user guide")
- textBold : true
- onClicked : Qt.openUrlExternally("https://protonmail.com/support/categories/import-export/")
- }
- }
-
- function guessEmailProvider() {
- var splitMail = inputEmail.text.split("@")
- //console.log("finished ", splitMail)
- if (splitMail.length != 2) return
- switch (splitMail[1]){
- case "yandex.ru":
- case "yandex.com":
- case "ya.ru":
- inputServer.text = "imap.yandex.ru"
- inputPort.text = "993"
- break
- case "outlook.com":
- case "hotmail.com":
- case "live.com":
- case "live.ru":
- inputServer.text = "imap-mail.outlook.com"
- inputPort.text = "993"
- break
- case "seznam.cz":
- case "email.cz":
- case "post.cz":
- inputServer.text = "imap.seznam.cz"
- inputPort.text = "993"
- break
- case "gmx.de":
- inputServer.text = "imap.gmx.net"
- inputPort.text = "993"
- break
- case "rundbox.com":
- inputServer.text = "mail."+splitMail[1]
- inputPort.text = "993"
- break
- case "fastmail.com":
- case "aol.com":
- case "orange.fr":
- case "hushmail.com":
- case "ntlworld.com":
- case "aol.com":
- case "gmx.com":
- case "mail.com":
- case "mail.ru":
- case "gmail.com":
- inputServer.text = "imap."+splitMail[1]
- inputPort.text = "993"
- break
- case (splitMail[1].match(/^yahoo\./) || {}).input:
- inputServer.text = "imap.mail.yahoo.com"
- inputPort.text = "993"
- break
- default:
- }
-
- return
- }
-
- function setServerParams() {
- switch (emailProvider.currentIndex) {
- case 1:
- inputServer.text = "imap.gmail.com"
- inputPort.text = "993"
- break
- case 2:
- inputServer.text = "imap.yandex.com"
- inputPort.text = "993"
- break
- case 3:
- inputServer.text = "imap.outlook.com"
- inputPort.text = "993"
- break
- case 4:
- inputServer.text = "imap.yahoo.com"
- inputPort.text = "993"
- break
- }
-
- return
- }
-
- function update_label_time() {
- var d = new Date();
- var outstring = " "
- outstring+=qsTr("Import")
- outstring+="-"
- outstring+=d.getDate()
- outstring+="-"
- outstring+=d.getMonth()+1
- outstring+="-"
- outstring+=d.getFullYear()
- outstring+=" "
- outstring+=d.getHours()
- outstring+=":"
- outstring+=d.getMinutes()
- outstring+=" "
- importLabel.text = outstring
- }
-
- function clear() {
- root.inputPath = ""
- clear_status()
- inputEmail.clear()
- inputPassword.clear()
- inputServer.clear()
- inputPort.clear()
- reportList.hide()
- globalLabels.reset()
- }
-
- PopupMessage {
- id: errorPopup
- width : parent.width
- height : parent.height
- msgWidth : root.width * 0.6108
- }
-
- Connections {
- target: errorPopup
-
- onClickedOkay : errorPopup.hide()
-
- onClickedYes : {
- if (errorPopup.msgID == "ask_send_report") {
- errorPopup.hide()
- root.report_sent(go.sendImportReport(root.address))
- return
- }
- root.cancel()
- errorPopup.hide()
- }
- onClickedNo : {
- errorPopup.hide()
- }
-
- onClickedRetry : {
- go.answerRetry()
- errorPopup.hide()
- }
- onClickedSkip : {
- go.answerSkip(
- errorPopup.checkbox.text == root.msgDontShowAgain &&
- errorPopup.checkbox.checked
- )
- errorPopup.hide()
- }
- onClickedCancel : {
- root.cancel()
- errorPopup.hide()
- }
-
- /*
- onClickedCancel : {
- errorPopup.hide()
- root.ask_cancel_progress()
- }
- */
- }
-
-
- function check_inputs() {
- var isOK = true
- switch (currentIndex) {
- case 0: // select source
- var res = go.checkPathStatus(root.inputPath)
- isOK = (
- (res&gui.enums.pathOK)==gui.enums.pathOK &&
- (res&gui.enums.pathNotADir)==0 && // is a dir
- (res&gui.enums.pathDirEmpty)==0 // is nonempty
- )
- if (!isOK) errorPopup.show(qsTr("Please select non-empty folder."))
- break
- // check directory
- case 1: // imap settings
- if (!(
- inputEmail . checkNonEmpty() &&
- inputPassword . checkNonEmpty() &&
- inputServer . checkNonEmpty() &&
- inputPort . checkNonEmpty() &&
- inputPort . checkIsANumber()
- //emailProvider . currentIndex!=0
- )) isOK = false
- if (winMain.updateState == gui.enums.statusNoInternet) { // todo: use main error dialog for this
- errorPopup.show(qsTr("Please check your internet connection."))
- return false
- }
- break
- case 2: // loading structure
- if (winMain.updateState == gui.enums.statusNoInternet) {
- errorPopup.show(qsTr("Please check your internet connection."))
- return false
- }
- break
- case 3: // import insturctions
- /*
- console.log(" ====== TODO ======== ")
- if (!structureExternal.hasTarget()) {
- errorPopup.show(qsTr("Nothing selected for import."))
- return false
- }
- */
- break
- case 4: // import status
- }
- return isOK
- }
-
- onCancel: {
- switch (currentIndex) {
- case DialogImport.Page.ImapSource:
- case DialogImport.Page.LoadingStructure:
- root.clear()
- root.currentIndex=0
- break
- case DialogImport.Page.SelectSourceType:
- case DialogImport.Page.SourceToTarget:
- case DialogImport.Page.Report:
- root.hide()
- break
- case DialogImport.Page.Progress:
- go.cancelProcess()
- root.currentIndex=3
- root.clear_status()
- globalLabels.reset()
- break
- }
- }
-
- onOkay: {
- var isOK = check_inputs()
- if (isOK) {
- timer.interval= currentIndex==0 || currentIndex==4 ? 10 : 300
- switch (currentIndex) {
- case DialogImport.Page.SelectSourceType: // select source
- currentIndex=2
- break
-
- case DialogImport.Page.SourceToTarget:
- globalDateRange.applyRange()
- if (globalLabels.labelSelected) {
- var isOK = go.createLabelOrFolder(
- winMain.dialogImport.address,
- globalLabels.labelName,
- globalLabels.labelColor,
- true,
- "-1"
- )
- if (!isOK) return
- }
- incrementCurrentIndex()
- break
-
- case DialogImport.Page.Report:
- root.clear_status()
- root.hide()
- break
-
- case DialogImport.Page.LoadingStructure:
- globalLabels.reset()
- // TODO_: importInstructions.hasItems = (structureExternal.rowCount() > 0)
- importInstructions.hasItems = true
- case DialogImport.Page.ImapSource:
- default:
- incrementCurrentIndex()
- }
- timer.start()
- }
- }
-
- onShow : {
- root.clear()
- if (winMain.updateState==gui.enums.statusNoInternet) {
- if (winMain.updateState==gui.enums.statusNoInternet) {
- winMain.popupMessage.show(go.canNotReachAPI)
- root.hide()
- }
- }
- }
-
- onHide : {
- root.clear()
- }
-
- function clear_status() { // TODO: move this to Gui.qml
- go.progress=0.0
- go.progressFails=0.0
- go.total=0.0
- go.progressDescription=gui.enums.progressInit
- }
-
- function ask_send_report(){
- errorPopup.msgID="ask_send_report"
- errorPopup.buttonYes.visible = true
- errorPopup.buttonNo.visible = true
- errorPopup.buttonOkay.visible = false
- errorPopup.show (qsTr("Program will send the report of finished import process to our customer support. The report was filtered to remove all personal information.\n\nDo you want to send report?"))
- }
-
- function report_sent(isOK){
- errorPopup.msgID="report_sent"
- if (isOK) {
- errorPopup.show (qsTr("Report sent successfully."))
- } else {
- errorPopup.show (qsTr("Not able to send report. Please contact customer support at importexport@protonmail.com"))
- }
- }
-
- function ask_cancel_progress(){
- errorPopup.msgID="ask_cancel_progress"
- errorPopup.buttonYes.visible = true
- errorPopup.buttonNo.visible = true
- errorPopup.buttonOkay.visible = false
- errorPopup.show (qsTr("Are you sure you want to cancel this import?"))
- }
-
- function ask_retry_skip_cancel(subject,errorMessage){
- errorPopup.msgID="ask_retry_skip_cancel"
- errorPopup.buttonYes.visible = false
- errorPopup.buttonNo.visible = false
- errorPopup.buttonOkay.visible = false
-
- errorPopup.buttonRetry.visible = true
- errorPopup.buttonSkip.visible = true
- errorPopup.buttonCancel.visible = true
-
- errorPopup.checkbox.text = root.msgDontShowAgain
-
- errorPopup.show(
- qsTr(
- "Cannot import message \"%1\"\n\n%2\nCancel will stop the entire import.",
- "error message while importing: arg1 is message subject, arg2 is error message"
- ).arg(subject).arg(errorMessage)
- )
- }
-
- function sanitizePath(path) {
- var pattern = "file://"
- if (go.goos=="windows") pattern+="/"
- root.inputPath = path.replace(pattern, "")
- }
-
- Connections {
- target: timer
- onTriggered: {
- switch (currentIndex) {
- case DialogImport.Page.SelectSourceType:
- case DialogImport.Page.ImapSource:
- case DialogImport.Page.SourceToTarget:
- globalDateRange.getRange()
- break
- case DialogImport.Page.LoadingStructure:
- go.setupAndLoadForImport(
- root.isFromIMAP,
- root.inputPath,
- inputEmail.text, inputPassword.text, inputServer.text, inputPort.text,
- root.account,
- root.address
- )
- break
- case DialogImport.Page.Progress:
- go.startImport(root.address, importEncrypted.checked)
- break
- }
- }
- }
-}
diff --git a/internal/frontend/qml/ImportExportUI/DialogYesNo.qml b/internal/frontend/qml/ImportExportUI/DialogYesNo.qml
deleted file mode 100644
index 164d4892..00000000
--- a/internal/frontend/qml/ImportExportUI/DialogYesNo.qml
+++ /dev/null
@@ -1,353 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// Dialog with Yes/No buttons
-
-import QtQuick 2.8
-import QtQuick.Controls 2.2
-import ProtonUI 1.0
-import ImportExportUI 1.0
-
-Dialog {
- id: root
-
- title : ""
-
- property string input
-
- property alias question : msg.text
- property alias note : noteText.text
- property alias answer : answ.text
- property alias buttonYes : buttonYes
- property alias buttonNo : buttonNo
-
- isDialogBusy: currentIndex==1
-
- signal confirmed()
-
- Column {
- id: dialogMessage
- property int heightInputs : msg.height+
- middleSep.height+
- buttonRow.height +
- (checkboxSep.visible ? checkboxSep.height : 0 ) +
- (noteSep.visible ? noteSep.height : 0 ) +
- (checkBoxWrapper.visible ? checkBoxWrapper.height : 0 ) +
- (root.note!="" ? noteText.height : 0 )
-
- Rectangle { color : "transparent"; width : Style.main.dummy; height : (root.height-dialogMessage.heightInputs)/2 }
-
- AccessibleText {
- id:noteText
- anchors.horizontalCenter: parent.horizontalCenter
- color: Style.dialog.text
- font {
- pointSize: Style.dialog.fontSize * Style.pt
- bold: false
- }
- width: 2*root.width/3
- horizontalAlignment: Text.AlignHCenter
- wrapMode: Text.Wrap
- }
- Rectangle { id: noteSep; visible: note!=""; color : "transparent"; width : Style.main.dummy; height : Style.dialog.heightSeparator}
-
- AccessibleText {
- id: msg
- anchors.horizontalCenter: parent.horizontalCenter
- color: Style.dialog.text
- font {
- pointSize: Style.dialog.fontSize * Style.pt
- bold: true
- }
- width: 2*parent.width/3
- text : ""
- horizontalAlignment: Text.AlignHCenter
- wrapMode: Text.Wrap
- }
-
- Rectangle { id: checkboxSep; visible: checkBoxWrapper.visible; color : "transparent"; width : Style.main.dummy; height : Style.dialog.heightSeparator}
- Row {
- id: checkBoxWrapper
- property bool isChecked : false
- visible: root.state=="deleteUser"
- anchors.horizontalCenter: parent.horizontalCenter
- spacing: Style.dialog.spacing
-
- function toggle() {
- checkBoxWrapper.isChecked = !checkBoxWrapper.isChecked
- }
-
- Text {
- id: checkbox
- font {
- pointSize : Style.dialog.iconSize * Style.pt
- family : Style.fontawesome.name
- }
- anchors.verticalCenter : parent.verticalCenter
- text: checkBoxWrapper.isChecked ? Style.fa.check_square_o : Style.fa.square_o
- color: checkBoxWrapper.isChecked ? Style.main.textBlue : Style.main.text
-
- MouseArea {
- anchors.fill: parent
- onPressed: checkBoxWrapper.toggle()
- cursorShape: Qt.PointingHandCursor
- }
- }
- Text {
- id: checkBoxNote
- anchors.verticalCenter : parent.verticalCenter
- text: qsTr("Additionally delete all stored preferences and data", "when removing an account, this extra preference additionally deletes all cached data")
- color: Style.main.text
- font.pointSize: Style.dialog.fontSize * Style.pt
-
- MouseArea {
- anchors.fill: parent
- onPressed: checkBoxWrapper.toggle()
- cursorShape: Qt.PointingHandCursor
-
- Accessible.role: Accessible.CheckBox
- Accessible.checked: checkBoxWrapper.isChecked
- Accessible.name: checkBoxNote.text
- Accessible.description: checkBoxNote.text
- Accessible.ignored: checkBoxNote.text == ""
- Accessible.onToggleAction: checkBoxWrapper.toggle()
- Accessible.onPressAction: checkBoxWrapper.toggle()
- }
- }
- }
-
- Rectangle { id: middleSep; color : "transparent"; width : Style.main.dummy; height : 2*Style.dialog.heightSeparator }
-
- Row {
- id: buttonRow
- anchors.horizontalCenter: parent.horizontalCenter
- spacing: Style.dialog.spacing
- ButtonRounded {
- id:buttonNo
- color_main : Style.dialog.textBlue
- fa_icon : Style.fa.times
- text : qsTr("No")
- onClicked : root.hide()
- }
- ButtonRounded {
- id: buttonYes
- color_main : Style.dialog.background
- color_minor : Style.dialog.textBlue
- isOpaque : true
- fa_icon : Style.fa.check
- text : qsTr("Yes")
- onClicked : {
- currentIndex=1
- root.confirmed()
- }
- }
- }
- }
-
-
- Column {
- Rectangle { color : "transparent"; width : Style.main.dummy; height : (root.height-answ.height)/2 }
- AccessibleText {
- id: answ
- anchors.horizontalCenter: parent.horizontalCenter
- color: Style.dialog.text
- font {
- pointSize : Style.dialog.fontSize * Style.pt
- bold : true
- }
- width: 3*parent.width/4
- horizontalAlignment: Text.AlignHCenter
- text : qsTr("Waiting...", "in general this displays between screens when processing data takes a long time")
- wrapMode: Text.Wrap
- }
- }
-
-
- states : [
- State {
- name: "quit"
- PropertyChanges {
- target: root
- currentIndex : 0
- title : qsTr("Close ImportExport", "quits the application")
- question : qsTr("Are you sure you want to close the ImportExport?", "asked when user tries to quit the application")
- note : ""
- answer : qsTr("Closing ImportExport...", "displayed when user is quitting application")
- }
- },
- State {
- name: "logout"
- PropertyChanges {
- target: root
- currentIndex : 1
- title : qsTr("Logout", "title of page that displays during account logout")
- question : ""
- note : ""
- answer : qsTr("Logging out...", "displays during account logout")
- }
- },
- State {
- name: "deleteUser"
- PropertyChanges {
- target: root
- currentIndex : 0
- title : qsTr("Delete account", "title of page that displays during account deletion")
- question : qsTr("Are you sure you want to remove this account?", "displays during account deletion")
- note : ""
- answer : qsTr("Deleting ...", "displays during account deletion")
- }
- },
- State {
- name: "clearChain"
- PropertyChanges {
- target : root
- currentIndex : 0
- title : qsTr("Clear keychain", "title of page that displays during keychain clearing")
- question : qsTr("Are you sure you want to clear your keychain?", "displays during keychain clearing")
- note : qsTr("This will remove all accounts that you have added to the Import-Export app.", "displays during keychain clearing")
- answer : qsTr("Clearing the keychain ...", "displays during keychain clearing")
- }
- },
- State {
- name: "clearCache"
- PropertyChanges {
- target: root
- currentIndex : 0
- title : qsTr("Clear cache", "title of page that displays during cache clearing")
- question : qsTr("Are you sure you want to clear your local cache?", "displays during cache clearing")
- note : qsTr("This will delete all of your stored preferences.", "displays during cache clearing")
- answer : qsTr("Clearing the cache ...", "displays during cache clearing")
- }
- },
- State {
- name: "checkUpdates"
- PropertyChanges {
- target: root
- currentIndex : 1
- title : ""
- question : ""
- note : ""
- answer : qsTr("Checking for updates ...", "displays if user clicks the Check for Updates button in the Help tab")
- }
- },
- State {
- name: "internetCheck"
- PropertyChanges {
- target: root
- currentIndex : 1
- title : ""
- question : ""
- note : ""
- answer : qsTr("Contacting server...", "displays if user clicks the Check for Updates button in the Help tab")
- }
- },
- State {
- name: "addressmode"
- PropertyChanges {
- target: root
- currentIndex : 0
- title : ""
- question : qsTr("Do you want to continue?", "asked when the user changes between split and combined address mode")
- note : qsTr("Changing between split and combined address mode will require you to delete your account(s) from your email client and begin the setup process from scratch.", "displayed when the user changes between split and combined address mode")
- answer : qsTr("Configuring address mode for ", "displayed when the user changes between split and combined address mode") + root.input
- }
- },
- State {
- name: "toggleAutoStart"
- PropertyChanges {
- target: root
- currentIndex : 1
- question : ""
- note : ""
- title : ""
- answer : {
- var msgTurnOn = qsTr("Turning on automatic start of ImportExport...", "when the automatic start feature is selected")
- var msgTurnOff = qsTr("Turning off automatic start of ImportExport...", "when the automatic start feature is deselected")
- return go.isAutoStart==0 ? msgTurnOff : msgTurnOn
- }
- }
- },
- State {
- name: "undef";
- PropertyChanges {
- target: root
- currentIndex : 1
- question : ""
- note : ""
- title : ""
- answer : ""
- }
- }
- ]
-
-
- Shortcut {
- sequence: StandardKey.Cancel
- onActivated: root.hide()
- }
-
- Shortcut {
- sequence: "Enter"
- onActivated: root.confirmed()
- }
-
- onHide: {
- checkBoxWrapper.isChecked = false
- state = "undef"
- }
-
- onShow: {
- // hide all other dialogs
- winMain.dialogAddUser .visible = false
- winMain.dialogCredits .visible = false
- // dialogFirstStart should reappear again after closing global
- root.visible = true
- }
-
-
-
- onConfirmed : {
- if (state == "quit" || state == "instance exists" ) {
- timer.interval = 1000
- } else {
- timer.interval = 300
- }
- answ.forceActiveFocus()
- timer.start()
- }
-
- Connections {
- target: timer
- onTriggered: {
- if ( state == "addressmode" ) { go.switchAddressMode (input) }
- if ( state == "clearChain" ) { go.clearKeychain () }
- if ( state == "clearCache" ) { go.clearCache () }
- if ( state == "deleteUser" ) { go.deleteAccount (input, checkBoxWrapper.isChecked) }
- if ( state == "logout" ) { go.logoutAccount (input) }
- if ( state == "toggleAutoStart" ) { go.toggleAutoStart () }
- if ( state == "quit" ) { Qt.quit () }
- if ( state == "instance exists" ) { Qt.quit () }
- if ( state == "checkUpdates" ) { }
- }
- }
-
- Keys.onPressed: {
- if (event.key == Qt.Key_Enter) {
- root.confirmed()
- }
- }
-}
diff --git a/internal/frontend/qml/ImportExportUI/ExportStructure.qml b/internal/frontend/qml/ImportExportUI/ExportStructure.qml
deleted file mode 100644
index e6216f7f..00000000
--- a/internal/frontend/qml/ImportExportUI/ExportStructure.qml
+++ /dev/null
@@ -1,149 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// List of export folders / labels
-import QtQuick 2.8
-import QtQuick.Controls 2.2
-import ProtonUI 1.0
-import ImportExportUI 1.0
-
-Rectangle {
- id: root
- color : Style.exporting.background
- radius : Style.exporting.boxRadius
- border {
- color : Style.exporting.line
- width : Style.dialog.borderInput
- }
- property bool hasItems: true
-
-
- Text { // placeholder
- visible: !root.hasItems
- anchors.centerIn: parent
- color: Style.main.textDisabled
- font {
- pointSize: Style.dialog.fontSize * Style.pt
- }
- horizontalAlignment: Text.AlignHCenter
- verticalAlignment: Text.AlignVCenter
- text: qsTr("No emails found for this address.","todo")
- }
-
-
- property string title : ""
-
- TextMetrics {
- id: titleMetrics
- text: root.title
- elide: Qt.ElideMiddle
- elideWidth: root.width - 4*Style.exporting.leftMargin
- font {
- pointSize: Style.dialog.fontSize * Style.pt
- bold: true
- }
- }
-
- Rectangle {
- id: header
- anchors {
- top: root.top
- left: root.left
- }
- width : root.width
- height : Style.dialog.fontSize*3
- color : Style.transparent
- Rectangle {
- anchors.bottom: parent.bottom
- color : Style.exporting.line
- height : Style.dialog.borderInput
- width : parent.width
- }
-
- Text {
- anchors {
- left : parent.left
- leftMargin : 2*Style.exporting.leftMargin
- verticalCenter : parent.verticalCenter
- }
- color: Style.dialog.text
- font: titleMetrics.font
- text: titleMetrics.elidedText
- }
- }
-
-
- ListView {
- id: listview
- clip : true
- orientation : ListView.Vertical
- boundsBehavior : Flickable.StopAtBounds
- model : transferRules
- cacheBuffer : 10000
-
- anchors {
- left : root.left
- right : root.right
- bottom : root.bottom
- top : header.bottom
- margins : Style.dialog.borderInput
- }
-
- ScrollBar.vertical: ScrollBar {
- /*
- policy: ScrollBar.AsNeeded
- background : Rectangle {
- color : Style.exporting.sliderBackground
- radius : Style.exporting.boxRadius
- }
- contentItem : Rectangle {
- color : Style.exporting.sliderForeground
- radius : Style.exporting.boxRadius
- implicitWidth : Style.main.rightMargin / 3
- }
- */
- anchors {
- right: parent.right
- rightMargin: Style.main.rightMargin/4
- }
- width: Style.main.rightMargin/3
- Accessible.ignored: true
- }
-
- delegate: FolderRowButton {
- property variant modelData: model
- width : root.width - 5*root.border.width
- type : modelData.type
- folderIconColor : modelData.iconColor
- title : modelData.name
- isSelected : modelData.isActive
- onClicked : {
- //console.log("Clicked", folderId, isSelected)
- transferRules.setIsRuleActive(modelData.mboxID,!model.isActive)
- }
- }
-
- section.property: "type"
- section.delegate: FolderRowButton {
- isSection : true
- width : root.width - 5*root.border.width
- title : gui.folderTypeTitle(section)
- isSelected : section == gui.enums.folderTypeLabel ? transferRules.isLabelGroupSelected : transferRules.isFolderGroupSelected
- onClicked : transferRules.setIsGroupActive(section,!isSelected)
- }
- }
-}
diff --git a/internal/frontend/qml/ImportExportUI/FilterStructure.qml b/internal/frontend/qml/ImportExportUI/FilterStructure.qml
deleted file mode 100644
index dc9614f6..00000000
--- a/internal/frontend/qml/ImportExportUI/FilterStructure.qml
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// Filter only selected folders or labels
-import QtQuick 2.8
-import QtQml.Models 2.2
-
-
-DelegateModel {
- id: root
- model : structurePM
- //filterOnGroup : root.folderType
- //delegate : root.delegate
- groups : [
- DelegateModelGroup {name: gui.enums.folderTypeFolder ; includeByDefault: false},
- DelegateModelGroup {name: gui.enums.folderTypeLabel ; includeByDefault: false}
- ]
-
- function updateFilter() {
- //console.log("FilterModelDelegate::UpdateFilter")
- // filter
- var rowCount = root.items.count;
- for (var iItem = 0; iItem < rowCount; iItem++) {
- var entry = root.items.get(iItem);
- entry.inLabel = (
- root.filterOnGroup == gui.enums.folderTypeLabel &&
- entry.model.folderType == gui.enums.folderTypeLabel
- )
- entry.inFolder = (
- root.filterOnGroup == gui.enums.folderTypeFolder &&
- entry.model.folderType != gui.enums.folderTypeLabel
- )
- /*
- if (entry.inFolder && entry.model.folderId == selectedIDs) {
- view.currentIndex = iItem
- }
- */
- //console.log("::::update filter:::::", iItem, entry.model.folderName, entry.inFolder, entry.inLabel)
- }
- }
-}
diff --git a/internal/frontend/qml/ImportExportUI/FolderRowButton.qml b/internal/frontend/qml/ImportExportUI/FolderRowButton.qml
deleted file mode 100644
index ed594333..00000000
--- a/internal/frontend/qml/ImportExportUI/FolderRowButton.qml
+++ /dev/null
@@ -1,99 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// Checkbox row for folder selection
-import QtQuick 2.8
-import QtQuick.Controls 2.2
-import ProtonUI 1.0
-import ImportExportUI 1.0
-
-AccessibleButton {
- id: root
-
- property bool isSection : false
- property bool isSelected : false
- property string title : "N/A"
- property string type : ""
- property string folderIconColor : Style.main.textBlue
-
- height : Style.exporting.rowHeight
- padding : 0.0
- anchors {
- horizontalCenter: parent.horizontalCenter
- }
-
- background: Rectangle {
- color: isSection ? Style.exporting.background : Style.exporting.rowBackground
- Rectangle { // line
- anchors.bottom : parent.bottom
- height : Style.dialog.borderInput
- width : parent.width
- color : Style.exporting.background
- }
- }
-
- contentItem: Rectangle {
- color: "transparent"
- id: content
- Text {
- id: checkbox
- anchors {
- verticalCenter : parent.verticalCenter
- left : content.left
- leftMargin : Style.exporting.leftMargin * (root.type == gui.enums.folderTypeSystem ? 1.0 : 2.0)
- }
- font {
- family : Style.fontawesome.name
- pointSize : Style.dialog.fontSize * Style.pt
- }
- color : isSelected ? Style.main.text : Style.main.textInactive
- text : (isSelected ? Style.fa.check_square_o : Style.fa.square_o )
- }
-
- Text { // icon
- id: folderIcon
- visible: !isSection
- anchors {
- verticalCenter : parent.verticalCenter
- left : checkbox.left
- leftMargin : Style.dialog.fontSize + Style.exporting.leftMargin
- }
- color : root.type=="" ? Style.main.textBlue : root.folderIconColor
- font {
- family : Style.fontawesome.name
- pointSize : Style.dialog.fontSize * Style.pt
- }
- text : {
- return gui.folderIcon(root.title.toLowerCase(), root.type)
- }
- }
-
- Text {
- text: root.title
- anchors {
- verticalCenter : parent.verticalCenter
- left : isSection ? checkbox.left : folderIcon.left
- leftMargin : Style.dialog.fontSize + Style.exporting.leftMargin
- }
- font {
- pointSize : Style.dialog.fontSize * Style.pt
- bold: isSection
- }
- color: Style.exporting.text
- }
- }
-}
diff --git a/internal/frontend/qml/ImportExportUI/HelpView.qml b/internal/frontend/qml/ImportExportUI/HelpView.qml
deleted file mode 100644
index 00c81b48..00000000
--- a/internal/frontend/qml/ImportExportUI/HelpView.qml
+++ /dev/null
@@ -1,138 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// List the settings
-
-import QtQuick 2.8
-import ProtonUI 1.0
-import ImportExportUI 1.0
-
-Item {
- id: root
-
- // must have wrapper
- Rectangle {
- id: wrapper
- anchors.centerIn: parent
- width: parent.width
- height: parent.height
- color: Style.main.background
-
- // content
- Column {
- anchors.horizontalCenter : parent.horizontalCenter
-
-
- ButtonIconText {
- id: manual
- anchors.left: parent.left
- text: qsTr("Setup Guide")
- leftIcon.text : Style.fa.book
- rightIcon.text : Style.fa.chevron_circle_right
- rightIcon.font.pointSize : Style.settings.toggleSize * Style.pt
- onClicked: go.openManual()
- }
-
- ButtonIconText {
- id: updates
- anchors.left: parent.left
- text: qsTr("Check for Updates")
- leftIcon.text : Style.fa.refresh
- rightIcon.text : Style.fa.chevron_circle_right
- rightIcon.font.pointSize : Style.settings.toggleSize * Style.pt
- onClicked: {
- go.checkForUpdates()
- }
- }
-
- Rectangle {
- anchors.horizontalCenter : parent.horizontalCenter
- height: Math.max (
- aboutText.height +
- Style.main.fontSize,
- wrapper.height - (
- 2*manual.height +
- creditsLink.height +
- Style.main.fontSize
- )
- )
- width: wrapper.width
- color : Style.transparent
- AccessibleText {
- id: aboutText
- anchors {
- bottom: parent.bottom
- horizontalCenter: parent.horizontalCenter
- }
- color: Style.main.textDisabled
- horizontalAlignment: Qt.AlignHCenter
- font.pointSize : Style.main.fontSize * Style.pt
- text: "ProtonMail Import-Export app Version "+go.getBackendVersion()+"\n© 2021 Proton Technologies AG"
- }
- }
-
- Row {
- anchors.horizontalCenter : parent.horizontalCenter
- spacing : Style.main.dummy
-
- Text {
- id: creditsLink
- text : qsTr("Credits", "link to click on to view list of credited libraries")
- color : Style.main.textDisabled
- font.pointSize: Style.main.fontSize * Style.pt
- font.underline: true
- MouseArea {
- anchors.fill: parent
- onClicked : {
- winMain.dialogCredits.show()
- }
- cursorShape: Qt.PointingHandCursor
- }
- }
-
- Text {
- id: licenseFile
- text : qsTr("License", "link to click on to open license file")
- color : Style.main.textDisabled
- font.pointSize: Style.main.fontSize * Style.pt
- font.underline: true
- MouseArea {
- anchors.fill: parent
- onClicked : {
- go.openLicenseFile()
- }
- cursorShape: Qt.PointingHandCursor
- }
- }
-
- Text {
- id: releaseNotes
- text : qsTr("Release notes", "link to click on to view release notes for this version of the app")
- color : Style.main.textDisabled
- font.pointSize: Style.main.fontSize * Style.pt
- font.underline: true
- MouseArea {
- anchors.fill: parent
- onClicked : gui.openReleaseNotes()
- cursorShape: Qt.PointingHandCursor
- }
- }
- }
- }
- }
-}
-
diff --git a/internal/frontend/qml/ImportExportUI/IEStyle.qml b/internal/frontend/qml/ImportExportUI/IEStyle.qml
deleted file mode 100644
index db66c94c..00000000
--- a/internal/frontend/qml/ImportExportUI/IEStyle.qml
+++ /dev/null
@@ -1,106 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// Adjust Bridge Style
-
-import QtQuick 2.8
-import ImportExportUI 1.0
-import ProtonUI 1.0
-
-Item {
- Component.onCompleted : {
- //Style.refdpi = go.goos == "darwin" ? 86.0 : 96.0
- Style.pt = go.goos == "darwin" ? 93/Style.dpi : 80/Style.dpi
-
- Style.main.background = "#fff"
- Style.main.text = "#505061"
- Style.main.textInactive = "#686876"
- Style.main.line = "#dddddd"
- Style.main.width = 884 * Style.px
- Style.main.height = 422 * Style.px
- Style.main.leftMargin = 25 * Style.px
- Style.main.rightMargin = 25 * Style.px
-
- Style.title.background = Style.main.text
- Style.title.text = Style.main.background
-
- Style.tabbar.background = "#3D3A47"
- Style.tabbar.rightButton = "add account"
- Style.tabbar.spacingButton = 45*Style.px
-
- Style.accounts.backgroundExpanded = "#fafafa"
- Style.accounts.backgroundAddrRow = "#fff"
- Style.accounts.leftMargin2 = Style.main.width/2
- Style.accounts.leftMargin3 = 5.5*Style.main.width/8
-
-
- Style.dialog.background = "#fff"
- Style.dialog.text = Style.main.text
- Style.dialog.line = "#e2e2e2"
- Style.dialog.fontSize = 12 * Style.px
- Style.dialog.heightInput = 2.2*Style.dialog.fontSize
- Style.dialog.heightButton = Style.dialog.heightInput
- Style.dialog.borderInput = 1 * Style.px
-
- Style.bubble.background = "#595966"
- Style.bubble.paneBackground = "#454553"
- Style.bubble.text = "#fff"
- Style.bubble.width = 310 * Style.px
- Style.bubble.widthPane = 36 * Style.px
- Style.bubble.iconSize = 14 * Style.px
-
-
- // colors:
- // text: #515061
- // tick: #686876
- // blue icon: #9396cc
- // row bck: #f8f8f9
- // line: #ddddde or #e2e2e2
- //
- // slider bg: #e6e6e6
- // slider fg: #515061
- // info icon: #c3c3c8
- // input border: #ebebeb
- //
- // bubble color: #595966
- // bubble pane: #454553
- // bubble text: #fff
- //
- // indent folder
- //
- // Dimensions:
- // full width: 882px
- // leftMargin: 25px
- // rightMargin: 25px
- // rightMargin: 25px
- // middleSeparator: 69px
- // width folders: 416px or (width - separators) /2
- // width output: 346px or (width - separators) /2
- //
- // height from top to input begin: 78px
- // heightSeparator: 27px
- // height folder input: 26px
- //
- // buble width: 309px
- // buble left pane icon: 14px
- // buble left pane width: 36px or (2.5 icon width)
- // buble height: 46px
- // buble arrow height: 12px
- // buble arrow width: 14px
- // buble radius: 3-4px
- }
-}
diff --git a/internal/frontend/qml/ImportExportUI/ImportDelegate.qml b/internal/frontend/qml/ImportExportUI/ImportDelegate.qml
deleted file mode 100644
index 3b052656..00000000
--- a/internal/frontend/qml/ImportExportUI/ImportDelegate.qml
+++ /dev/null
@@ -1,154 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// List of import folder and their target
-import QtQuick 2.8
-import QtQuick.Controls 2.2
-import ProtonUI 1.0
-import ImportExportUI 1.0
-
-Rectangle {
- id: root
- color: Style.importing.rowBackground
- height: 40
- width: 300
- property real leftMargin1 : folderIcon.x - root.x
- property real leftMargin2 : selectFolder.x - root.x
- property real nameWidth : {
- var available = root.width
- available -= rowPlacement.children.length * rowPlacement.spacing // spacing between places
- available -= 3*rowPlacement.leftPadding // left, and 2x right
- available -= folderIcon.width
- available -= arrowIcon.width
- available -= dateRangeMenu.width
- return available/3.3 // source folder label, target folder menu, target labels menu, and 0.3x label list
- }
- property real iconWidth : nameWidth*0.3
-
- property bool isSourceSelected: isActive
- property string lastTargetFolder: "6" // Archive
- property string lastTargetLabels: "" // no flag by default
-
- property string sourceID : mboxID
- property string sourceName : name
-
- Rectangle {
- id: line
- anchors {
- left : parent.left
- right : parent.right
- bottom : parent.bottom
- }
- height : Style.main.border * 2
- color : Style.importing.rowLine
- }
-
- Row {
- id: rowPlacement
- spacing: Style.dialog.spacing
- leftPadding: Style.dialog.spacing*2
- anchors.verticalCenter : parent.verticalCenter
-
- CheckBoxLabel {
- id: checkBox
- anchors.verticalCenter : parent.verticalCenter
- checked: root.isSourceSelected
-
- onClicked: root.toggleImport()
- }
-
- Text {
- id: folderIcon
- text : gui.folderIcon(root.sourceName, gui.enums.folderTypeFolder)
- anchors.verticalCenter : parent.verticalCenter
- color: root.isSourceSelected ? Style.main.text : Style.main.textDisabled
- font {
- family : Style.fontawesome.name
- pointSize : Style.dialog.fontSize * Style.pt
- }
- }
-
- Text {
- text : root.sourceName
- width: nameWidth
- elide: Text.ElideRight
- anchors.verticalCenter : parent.verticalCenter
- color: folderIcon.color
- font.pointSize : Style.dialog.fontSize * Style.pt
- }
-
- Text {
- id: arrowIcon
- text : Style.fa.arrow_right
- anchors.verticalCenter : parent.verticalCenter
- color: Style.main.text
- font {
- family : Style.fontawesome.name
- pointSize : Style.dialog.fontSize * Style.pt
- }
- }
-
- SelectFolderMenu {
- id: selectFolder
- sourceID: root.sourceID
- targets: transferRules.targetFolders(root.sourceID)
- width: nameWidth
- anchors.verticalCenter : parent.verticalCenter
- enabled: root.isSourceSelected
- onDoNotImport: root.toggleImport()
- onImportToFolder: root.importToFolder(newTargetID)
- }
-
- SelectLabelsMenu {
- sourceID: root.sourceID
- targets: transferRules.targetLabels(root.sourceID)
- width: nameWidth
- anchors.verticalCenter : parent.verticalCenter
- enabled: root.isSourceSelected
- onAddTargetLabel: { transferRules.addTargetID(sourceID, newTargetID) }
- onRemoveTargetLabel: { transferRules.removeTargetID(sourceID, newTargetID) }
- }
-
- LabelIconList {
- colorList: labelColors=="" ? [] : labelColors.split(";")
- width: iconWidth
- anchors.verticalCenter : parent.verticalCenter
- enabled: root.isSourceSelected
- }
-
- DateRangeMenu {
- id: dateRangeMenu
- sourceID: root.sourceID
- sourceFromDate: fromDate
- sourceToDate: toDate
-
- enabled: root.isSourceSelected
- anchors.verticalCenter : parent.verticalCenter
-
- Component.onCompleted : dateRangeMenu.updateRange()
- }
- }
-
-
- function importToFolder(newTargetID) {
- transferRules.addTargetID(root.sourceID,newTargetID)
- }
-
- function toggleImport() {
- transferRules.setIsRuleActive(root.sourceID, !root.isSourceSelected)
- }
-}
diff --git a/internal/frontend/qml/ImportExportUI/ImportReport.qml b/internal/frontend/qml/ImportExportUI/ImportReport.qml
deleted file mode 100644
index 80fe834a..00000000
--- a/internal/frontend/qml/ImportExportUI/ImportReport.qml
+++ /dev/null
@@ -1,216 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// Import report modal
-import QtQuick 2.11
-import QtQuick.Controls 2.4
-import ProtonUI 1.0
-import ImportExportUI 1.0
-
-Rectangle {
- id: root
- color: "#aa101021"
- visible: false
-
- MouseArea { // disable bellow
- anchors.fill: root
- hoverEnabled: true
- }
-
- Rectangle {
- id:background
- color: Style.main.background
- anchors {
- fill : root
- topMargin : Style.main.rightMargin
- leftMargin : 2*Style.main.rightMargin
- rightMargin : 2*Style.main.rightMargin
- bottomMargin : 2.5*Style.main.rightMargin
- }
-
- ClickIconText {
- anchors {
- top : parent.top
- right : parent.right
- margins : .5* Style.main.rightMargin
- }
- iconText : Style.fa.times
- text : ""
- textColor : Style.main.textBlue
- onClicked : root.hide()
- Accessible.description : qsTr("Close dialog %1", "Click to exit modal.").arg(title.text)
- }
-
- Text {
- id: title
- text : qsTr("List of errors")
- font {
- pointSize: Style.dialog.titleSize * Style.pt
- }
- anchors {
- top : parent.top
- topMargin : 0.5*Style.main.rightMargin
- horizontalCenter : parent.horizontalCenter
- }
- }
-
- ListView {
- id: errorView
- anchors {
- left : parent.left
- right : parent.right
- top : title.bottom
- bottom : detailBtn.top
- margins : Style.main.rightMargin
- }
-
- clip : true
- flickableDirection : Flickable.HorizontalAndVerticalFlick
- contentWidth : errorView.rWall
- boundsBehavior : Flickable.StopAtBounds
-
- ScrollBar.vertical: ScrollBar {
- anchors {
- right : parent.right
- top : parent.top
- rightMargin : Style.main.rightMargin/4
- topMargin : Style.main.rightMargin
- }
- width: Style.main.rightMargin/3
- Accessible.ignored: true
- }
- ScrollBar.horizontal: ScrollBar {
- anchors {
- bottom : parent.bottom
- right : parent.right
- bottomMargin : Style.main.rightMargin/4
- rightMargin : Style.main.rightMargin
- }
- height: Style.main.rightMargin/3
- Accessible.ignored: true
- }
-
-
-
- property real rW1 : 150 *Style.px
- property real rW2 : 150 *Style.px
- property real rW3 : 100 *Style.px
- property real rW4 : 150 *Style.px
- property real rW5 : 550 *Style.px
- property real rWall : errorView.rW1+errorView.rW2+errorView.rW3+errorView.rW4+errorView.rW5
- property real pH : .5*Style.main.rightMargin
-
- model : errorList
- delegate : Rectangle {
- width : Math.max(errorView.width, row.width)
- height : row.height
-
- Row {
- id: row
-
- spacing : errorView.pH
- leftPadding : errorView.pH
- rightPadding : errorView.pH
- topPadding : errorView.pH
- bottomPadding : errorView.pH
-
- ImportReportCell { width : errorView.rW1; text : mailSubject }
- ImportReportCell { width : errorView.rW2; text : mailDate }
- ImportReportCell { width : errorView.rW3; text : inputFolder }
- ImportReportCell { width : errorView.rW4; text : mailFrom }
- ImportReportCell { width : errorView.rW5; text : errorMessage }
- }
-
- Rectangle {
- color : Style.main.line
- height : .8*Style.px
- width : parent.width
- anchors.left : parent.left
- anchors.bottom : parent.bottom
- }
- }
-
- headerPositioning: ListView.OverlayHeader
- header: Rectangle {
- height : viewHeader.height
- width : Math.max(errorView.width, viewHeader.width)
- color : Style.accounts.backgroundExpanded
- z : 2
-
- Row {
- id: viewHeader
-
- spacing : errorView.pH
- leftPadding : errorView.pH
- rightPadding : errorView.pH
- topPadding : .5*errorView.pH
- bottomPadding : .5*errorView.pH
-
- ImportReportCell { width : errorView.rW1 ; text : qsTr ( "SUBJECT" ); isHeader: true }
- ImportReportCell { width : errorView.rW2 ; text : qsTr ( "DATE/TIME" ); isHeader: true }
- ImportReportCell { width : errorView.rW3 ; text : qsTr ( "FOLDER" ); isHeader: true }
- ImportReportCell { width : errorView.rW4 ; text : qsTr ( "FROM" ); isHeader: true }
- ImportReportCell { width : errorView.rW5 ; text : qsTr ( "ERROR" ); isHeader: true }
- }
-
- Rectangle {
- color : Style.main.line
- height : .8*Style.px
- width : parent.width
- anchors.left : parent.left
- anchors.bottom : parent.bottom
- }
- }
- }
-
- Rectangle {
- anchors{
- fill : errorView
- margins : -radius
- }
- radius : 2* Style.px
- color : Style.transparent
- border {
- width : Style.px
- color : Style.main.line
- }
- }
-
- ButtonRounded {
- id: detailBtn
- fa_icon : Style.fa.file_text
- text : qsTr("Detailed file")
- color_main : Style.dialog.textBlue
- onClicked : go.importLogFileName == "" ? go.openLogs() : go.openReport()
-
- anchors {
- bottom : parent.bottom
- bottomMargin : 0.5*Style.main.rightMargin
- horizontalCenter : parent.horizontalCenter
- }
- }
- }
-
-
- function show() {
- root.visible = true
- }
-
- function hide() {
- root.visible = false
- }
-}
diff --git a/internal/frontend/qml/ImportExportUI/ImportReportCell.qml b/internal/frontend/qml/ImportExportUI/ImportReportCell.qml
deleted file mode 100644
index 32974a2b..00000000
--- a/internal/frontend/qml/ImportExportUI/ImportReportCell.qml
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// Import report modal
-import QtQuick 2.11
-import QtQuick.Controls 2.4
-import ProtonUI 1.0
-import ImportExportUI 1.0
-
-
-Rectangle {
- id: root
-
- property alias text : cellText.text
- property bool isHeader : false
- property bool isHovered : false
- property bool isWider : cellText.contentWidth > root.width
-
- width : 20*Style.px
- height : cellText.height
- z : root.isHovered ? 3 : 1
- color : Style.transparent
-
- Rectangle {
- anchors {
- fill : cellText
- margins : -2*Style.px
- }
- color : root.isWider ? Style.main.background : Style.transparent
- border {
- color : root.isWider ? Style.main.textDisabled : Style.transparent
- width : Style.px
- }
- }
-
- Text {
- id: cellText
- color : root.isHeader ? Style.main.textDisabled : Style.main.text
- elide : root.isHovered ? Text.ElideNone : Text.ElideRight
- width : root.isHovered ? cellText.contentWidth : root.width
- font {
- pointSize : Style.main.textSize * Style.pt
- }
- }
-
- MouseArea {
- anchors.fill : root
- hoverEnabled : !root.isHeader
- onEntered : { root.isHovered = true }
- onExited : { root.isHovered = false }
- }
-}
diff --git a/internal/frontend/qml/ImportExportUI/ImportSourceButton.qml b/internal/frontend/qml/ImportExportUI/ImportSourceButton.qml
deleted file mode 100644
index 3d8b9617..00000000
--- a/internal/frontend/qml/ImportExportUI/ImportSourceButton.qml
+++ /dev/null
@@ -1,89 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// Export dialog
-import QtQuick 2.8
-import QtQuick.Controls 2.2
-import ProtonUI 1.0
-import ImportExportUI 1.0
-
-
-
-Button {
- id: root
-
- width : 200
- height : icon.height + 4*tag.height
- scale : pressed ? 0.95 : 1.0
-
- property string iconText : Style.fa.ban
-
- background: Rectangle { color: "transparent" }
-
- contentItem: Rectangle {
- id: wrapper
- color: "transparent"
-
- Image {
- id: icon
- anchors {
- bottom : wrapper.bottom
- bottomMargin : tag.height*2.5
- horizontalCenter : wrapper.horizontalCenter
- }
- fillMode : Image.PreserveAspectFit
- width : Style.main.fontSize * 7
- mipmap : true
- source : "images/"+iconText+".png"
-
- }
-
- Row {
- spacing: Style.dialog.spacing
- anchors {
- bottom : wrapper.bottom
- horizontalCenter : wrapper.horizontalCenter
- }
-
- Text {
- id: tag
-
- text : Style.fa.plus_circle
- color : Qt.lighter( Style.dialog.textBlue, root.enabled ? 1.0 : 1.5)
-
- font {
- family : Style.fontawesome.name
- pointSize : Style.main.fontSize * Style.pt * 1.2
- }
- }
-
- Text {
- text : root.text
- color: tag.color
-
- font {
- family : tag.font.family
- pointSize : tag.font.pointSize
- weight : Font.DemiBold
- underline : true
- }
- }
- }
- }
-}
-
-
diff --git a/internal/frontend/qml/ImportExportUI/ImportStructure.qml b/internal/frontend/qml/ImportExportUI/ImportStructure.qml
deleted file mode 100644
index 448d13d3..00000000
--- a/internal/frontend/qml/ImportExportUI/ImportStructure.qml
+++ /dev/null
@@ -1,148 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// List of import folder and their target
-import QtQuick 2.8
-import QtQuick.Controls 2.2
-import ProtonUI 1.0
-import ImportExportUI 1.0
-
-Rectangle {
- id: root
- property string titleFrom
- property string titleTo
- property bool hasItems: true
-
- color : Style.transparent
-
- Rectangle {
- anchors.fill: root
- radius : Style.dialog.radiusButton
- color : Style.transparent
- border {
- color : Style.main.line
- width : 1.5*Style.dialog.borderInput
- }
-
-
- Text { // placeholder
- visible: !root.hasItems
- anchors.centerIn: parent
- color: Style.main.textDisabled
- font {
- pointSize: Style.dialog.fontSize * Style.pt
- }
- horizontalAlignment: Text.AlignHCenter
- verticalAlignment: Text.AlignVCenter
- text: qsTr("No emails found for this source.","todo")
- }
- }
-
- anchors {
- left : parent.left
- right : parent.right
- top : parent.top
- bottom : parent.bottom
-
- leftMargin : Style.main.leftMargin
- rightMargin : Style.main.leftMargin
- topMargin : Style.main.topMargin
- bottomMargin : Style.main.bottomMargin
- }
-
- ListView {
- id: listview
- clip : true
- orientation : ListView.Vertical
- boundsBehavior : Flickable.StopAtBounds
- model : transferRules
- cacheBuffer : 10000
- delegate : ImportDelegate {
- width: root.width
- }
-
- anchors {
- top: titleBox.bottom
- bottom: root.bottom
- left: root.left
- right: root.right
- margins : Style.dialog.borderInput
- bottomMargin: Style.dialog.radiusButton
- }
-
- ScrollBar.vertical: ScrollBar {
- anchors {
- right: parent.right
- rightMargin: Style.main.rightMargin/4
- }
- width: Style.main.rightMargin/3
- Accessible.ignored: true
- }
- }
-
- Rectangle {
- id: titleBox
- anchors {
- top: parent.top
- left: parent.left
- right: parent.right
- }
- height: Style.main.fontSize *2
- color : Style.transparent
-
- Text {
- id: textTitleFrom
- anchors {
- left: parent.left
- verticalCenter: parent.verticalCenter
- leftMargin: {
- if (listview.currentItem === null) return 0
- else return listview.currentItem.leftMargin1
- }
- }
- text: ""+qsTr("From:")+" " + root.titleFrom
- color: Style.main.text
- width: listview.currentItem === null ? 0 : (listview.currentItem.leftMargin2 - listview.currentItem.leftMargin1 - Style.dialog.spacing)
- elide: Text.ElideMiddle
- }
-
- Text {
- id: textTitleTo
- anchors {
- left: parent.left
- verticalCenter: parent.verticalCenter
- leftMargin: {
- if (listview.currentIndex<0) return root.width/3
- else return listview.currentItem.leftMargin2
- }
- }
- text: ""+qsTr("To:")+" " + root.titleTo
- color: Style.main.text
- }
- }
-
- Rectangle {
- id: line
- anchors {
- left : titleBox.left
- right : titleBox.right
- top : titleBox.bottom
- }
- height: Style.dialog.borderInput
- color: Style.main.line
- }
-}
diff --git a/internal/frontend/qml/ImportExportUI/InlineDateRange.qml b/internal/frontend/qml/ImportExportUI/InlineDateRange.qml
deleted file mode 100644
index a5258973..00000000
--- a/internal/frontend/qml/ImportExportUI/InlineDateRange.qml
+++ /dev/null
@@ -1,128 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// input for date range
-import QtQuick 2.8
-import QtQuick.Controls 2.2
-import ProtonUI 1.0
-import ImportExportUI 1.0
-
-
-Row {
- id: dateRange
-
- property var structure : transferRules
- property string sourceID : "-1"
-
- property alias allDates : allDatesBox.checked
- property alias inputDateFrom : inputDateFrom
- property alias inputDateTo : inputDateTo
-
- property alias labelWidth: label.width
-
- function getRange() {common.getRange()}
- function applyRange() {common.applyRange()}
-
- DateRangeFunctions {id:common}
-
- spacing: Style.dialog.spacing*2
-
- Text {
- id: label
- anchors.verticalCenter: parent.verticalCenter
- text : qsTr("Date range")
- font {
- bold: true
- pointSize: Style.main.fontSize * Style.pt
- }
- color: Style.main.text
- }
-
- DateInput {
- id: inputDateFrom
- label: ""
- anchors.verticalCenter: parent.verticalCenter
- currentDate: new Date(0) // default epoch start
- maxDate: inputDateTo.currentDate
- }
-
- Text {
- text : Style.fa.arrows_h
- anchors.verticalCenter: parent.verticalCenter
- horizontalAlignment: Text.AlignHCenter
- verticalAlignment: Text.AlignVCenter
- color: Style.main.text
- font.family: Style.fontawesome.name
- }
-
- DateInput {
- id: inputDateTo
- label: ""
- anchors.verticalCenter: parent.verticalCenter
- currentDate: new Date() // default now
- minDate: inputDateFrom.currentDate
- isMaxDateToday: true
- }
-
- CheckBoxLabel {
- id: allDatesBox
- text : qsTr("All dates")
- anchors.verticalCenter : parent.verticalCenter
- checkedSymbol : Style.fa.toggle_on
- uncheckedSymbol : Style.fa.toggle_off
- uncheckedColor : Style.main.textDisabled
- symbolPointSize : Style.dialog.iconSize * Style.pt * 1.1
- spacing : Style.dialog.spacing*2
-
- TextMetrics {
- id: metrics
- text: allDatesBox.checkedSymbol
- font {
- family: Style.fontawesome.name
- pointSize: allDatesBox.symbolPointSize
- }
- }
-
-
- Rectangle {
- color: allDatesBox.checked ? dotBackground.color : Style.exporting.sliderBackground
- width: metrics.width*0.9
- height: metrics.height*0.6
- radius: height/2
- z: -1
-
- anchors {
- left: allDatesBox.left
- verticalCenter: allDatesBox.verticalCenter
- leftMargin: 0.05 * metrics.width
- }
-
- Rectangle {
- id: dotBackground
- color : Style.exporting.background
- height : parent.height
- width : height
- radius : height/2
- anchors {
- left : parent.left
- verticalCenter : parent.verticalCenter
- }
-
- }
- }
- }
-}
diff --git a/internal/frontend/qml/ImportExportUI/InlineLabelSelect.qml b/internal/frontend/qml/ImportExportUI/InlineLabelSelect.qml
deleted file mode 100644
index 9abc208d..00000000
--- a/internal/frontend/qml/ImportExportUI/InlineLabelSelect.qml
+++ /dev/null
@@ -1,225 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// input for date range
-import QtQuick 2.8
-import QtQuick.Controls 2.2
-import ProtonUI 1.0
-import ImportExportUI 1.0
-
-
-Row {
- id: root
- spacing: Style.dialog.spacing
-
- property alias labelWidth : label.width
-
- property string labelName : ""
- property string labelColor : ""
- property alias labelSelected : masterLabelCheckbox.checked
-
- Text {
- id: label
- text : qsTr("Add import label")
- font {
- bold: true
- pointSize: Style.main.fontSize * Style.pt
- }
- color: Style.main.text
- anchors.verticalCenter: parent.verticalCenter
- }
-
- InfoToolTip {
- info: qsTr( "When master import label is selected then all imported emails will have this label.", "Tooltip text for master import label")
- anchors.verticalCenter: parent.verticalCenter
- }
-
- CheckBoxLabel {
- id: masterLabelCheckbox
- text : ""
- anchors.verticalCenter : parent.verticalCenter
- checkedSymbol : Style.fa.toggle_on
- uncheckedSymbol : Style.fa.toggle_off
- uncheckedColor : Style.main.textDisabled
- symbolPointSize : Style.dialog.iconSize * Style.pt * 1.1
- spacing : Style.dialog.spacing*2
-
- TextMetrics {
- id: metrics
- text: masterLabelCheckbox.checkedSymbol
- font {
- family: Style.fontawesome.name
- pointSize: masterLabelCheckbox.symbolPointSize
- }
- }
-
-
- Rectangle {
- color: parent.checked ? dotBackground.color : Style.exporting.sliderBackground
- width: metrics.width*0.9
- height: metrics.height*0.6
- radius: height/2
- z: -1
-
- anchors {
- left: masterLabelCheckbox.left
- verticalCenter: masterLabelCheckbox.verticalCenter
- leftMargin: 0.05 * metrics.width
- }
-
- Rectangle {
- id: dotBackground
- color : Style.exporting.background
- height : parent.height
- width : height
- radius : height/2
- anchors {
- left : parent.left
- verticalCenter : parent.verticalCenter
- }
-
- }
- }
- }
-
- Rectangle {
- // label
- color : Style.transparent
- radius : Style.dialog.radiusButton
- border {
- color : Style.dialog.line
- width : Style.dialog.borderInput
- }
- anchors.verticalCenter : parent.verticalCenter
-
- scale: area.pressed ? 0.95 : 1
-
- width: content.width
- height: content.height
-
-
- Row {
- id: content
-
- spacing : Style.dialog.spacing
- padding : Style.dialog.spacing
-
- anchors.verticalCenter: parent.verticalCenter
-
- // label icon color
- Text {
- text: Style.fa.tag
- color: root.labelSelected ? root.labelColor : Style.dialog.line
- anchors.verticalCenter: parent.verticalCenter
- font {
- family: Style.fontawesome.name
- pointSize: Style.main.fontSize * Style.pt
- }
- }
-
- TextMetrics {
- id:labelMetrics
- text: root.labelName
- elide: Text.ElideRight
- elideWidth:gui.winMain.width*0.303
-
- font {
- pointSize: Style.main.fontSize * Style.pt
- }
- }
-
- // label text
- Text {
- text: labelMetrics.elidedText
- color: root.labelSelected ? Style.dialog.text : Style.dialog.line
- font: labelMetrics.font
- anchors.verticalCenter: parent.verticalCenter
- }
-
- // edit icon
- Text {
- text: Style.fa.edit
- color: root.labelSelected ? Style.main.textBlue : Style.dialog.line
- anchors.verticalCenter: parent.verticalCenter
- font {
- family: Style.fontawesome.name
- pointSize: Style.main.fontSize * Style.pt
- }
- }
- }
-
- MouseArea {
- id: area
- anchors.fill: parent
- enabled: root.labelSelected
- onClicked : {
- if (!root.labelSelected) return
- // NOTE: "createLater" is hack
- winMain.popupFolderEdit.show(root.labelName, "createLater", root.labelColor, gui.enums.folderTypeLabel, "")
- }
- }
- }
-
- function reset(){
- labelColor = go.leastUsedColor()
- labelName = qsTr("Imported", "default name of global label followed by date") + " " + gui.niceDateTime()
- labelSelected=true
- }
-
- Connections {
- target: winMain.popupFolderEdit
-
- onEdited : {
- if (newName!="") root.labelName = newName
- if (newColor!="") root.labelColor = newColor
- }
- }
-
-
- /*
- SelectLabelsMenu {
- id: labelMenu
- width : winMain.width/5
- sourceID : root.sourceID
- selectedIDs : root.structure.getTargetLabelIDs(root.sourceID)
- anchors.verticalCenter: parent.verticalCenter
- }
-
- LabelIconList {
- id: iconList
- selectedIDs : root.structure.getTargetLabelIDs(root.sourceID)
- anchors.verticalCenter: parent.verticalCenter
- }
-
-
- Connections {
- target: structureExternal
- onDataChanged: {
- iconList.selectedIDs = root.structure.getTargetLabelIDs(root.sourceID)
- labelMenu.selectedIDs = root.structure.getTargetLabelIDs(root.sourceID)
- }
- }
-
- Connections {
- target: structurePM
- onDataChanged:{
- iconList.selectedIDs = root.structure.getTargetLabelIDs(root.sourceID)
- labelMenu.selectedIDs = root.structure.getTargetLabelIDs(root.sourceID)
- }
- }
- */
-}
diff --git a/internal/frontend/qml/ImportExportUI/LabelIconList.qml b/internal/frontend/qml/ImportExportUI/LabelIconList.qml
deleted file mode 100644
index 10af07eb..00000000
--- a/internal/frontend/qml/ImportExportUI/LabelIconList.qml
+++ /dev/null
@@ -1,65 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// List of icons for selected folders
-import QtQuick 2.8
-import QtQuick.Controls 2.2
-import QtQml.Models 2.2
-import ProtonUI 1.0
-import ImportExportUI 1.0
-
-Rectangle {
- id: root
- width: Style.main.fontSize * 2
- height: metrics.height
- property var colorList
- color: "transparent"
-
- DelegateModel {
- id: selectedLabels
- model : colorList
- delegate : Text {
- text : metrics.text
- font : metrics.font
- color : modelData
- }
- }
-
- TextMetrics {
- id: metrics
- text: Style.fa.tag
- font {
- pointSize: Style.main.fontSize * Style.pt
- family: Style.fontawesome.name
- }
- }
-
- Row {
- anchors.left : root.left
- spacing : {
- var n = Math.max(2,root.colorList.length)
- var tagWidth = Math.max(1.0,metrics.width)
- var space = Math.min(1*Style.px, (root.width - n*tagWidth)/(n-1)) // not more than 1px
- space = Math.max(space,-tagWidth) // not less than tag width
- return space
- }
-
- Repeater {
- model: selectedLabels
- }
- }
-}
diff --git a/internal/frontend/qml/ImportExportUI/MainWindow.qml b/internal/frontend/qml/ImportExportUI/MainWindow.qml
deleted file mode 100644
index 96cfa672..00000000
--- a/internal/frontend/qml/ImportExportUI/MainWindow.qml
+++ /dev/null
@@ -1,415 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// This is main window
-
-import QtQuick 2.8
-import QtQuick.Window 2.2
-import QtQuick.Controls 2.1
-import QtQuick.Layouts 1.3
-import ImportExportUI 1.0
-import ProtonUI 1.0
-
-
-// Main Window
-Window {
- id : root
- property alias tabbar : tabbar
- property alias viewContent : viewContent
- property alias viewAccount : viewAccount
- property alias dialogAddUser : dialogAddUser
- property alias dialogGlobal : dialogGlobal
- property alias dialogCredits : dialogCredits
- property alias dialogUpdate : dialogUpdate
- property alias popupMessage : popupMessage
- property alias popupFolderEdit : popupFolderEdit
- property alias updateState : infoBar.state
- property alias dialogExport : dialogExport
- property alias dialogImport : dialogImport
- property alias addAccountTip : addAccountTip
- property int heightContent : height-titleBar.height
-
- property real innerWindowBorder : go.goos=="darwin" ? 0 : Style.main.border
-
- // main window appearance
- width : Style.main.width
- height : Style.main.height
- flags : go.goos=="darwin" ? Qt.Window : Qt.Window | Qt.FramelessWindowHint
- color: go.goos=="windows" ? Style.main.background : Style.transparent
- title: go.programTitle
-
- minimumWidth : Style.main.width
- minimumHeight : Style.main.height
-
- property bool isOutdateVersion : root.updateState == "forceUpdate"
-
- property bool activeContent :
- !dialogAddUser .visible &&
- !dialogCredits .visible &&
- !dialogGlobal .visible &&
- !dialogUpdate .visible &&
- !dialogImport .visible &&
- !dialogExport .visible &&
- !popupFolderEdit .visible &&
- !popupMessage .visible
-
- Accessible.role: Accessible.Grouping
- Accessible.description: qsTr("Window %1").arg(title)
- Accessible.name: Accessible.description
-
- WindowTitleBar {
- id: titleBar
- window: root
- visible: go.goos!="darwin"
- }
-
- Rectangle {
- anchors {
- top : titleBar.bottom
- left : parent.left
- right : parent.right
- bottom : parent.bottom
- }
- color: Style.title.background
- }
-
- InformationBar {
- id: infoBar
- anchors {
- left : parent.left
- right : parent.right
- top : titleBar.bottom
- leftMargin: innerWindowBorder
- rightMargin: innerWindowBorder
- }
- }
-
- TabLabels {
- id: tabbar
- currentIndex : 0
- enabled: root.activeContent
- anchors {
- top : infoBar.bottom
- right : parent.right
- left : parent.left
- leftMargin: innerWindowBorder
- rightMargin: innerWindowBorder
- }
- model: [
- { "title" : qsTr("Import-Export" , "title of tab that shows account list" ), "iconText": Style.fa.home },
- { "title" : qsTr("Settings" , "title of tab that allows user to change settings" ), "iconText": Style.fa.cogs },
- { "title" : qsTr("Help" , "title of tab that shows the help menu" ), "iconText": Style.fa.life_ring }
- ]
- }
-
- // Content of tabs
- StackLayout {
- id: viewContent
- enabled: root.activeContent
- // dimensions
- anchors {
- left : parent.left
- right : parent.right
- top : tabbar.bottom
- bottom : parent.bottom
- leftMargin: innerWindowBorder
- rightMargin: innerWindowBorder
- bottomMargin: innerWindowBorder
- }
- // attributes
- currentIndex : { return root.tabbar.currentIndex}
- clip : true
- // content
- AccountView {
- id : viewAccount
- onAddAccount : dialogAddUser.show()
- model : accountsModel
- hasFooter : false
- delegate : AccountDelegate {
- row_width : viewContent.width
- }
- }
- SettingsView { id: viewSettings; }
- HelpView { id: viewHelp; }
- }
-
-
- // Bubble prevent action
- Rectangle {
- anchors {
- left: parent.left
- right: parent.right
- top: titleBar.bottom
- bottom: parent.bottom
- }
- visible: bubbleNote.visible
- color: "#aa222222"
- MouseArea {
- anchors.fill: parent
- hoverEnabled: true
- }
- }
- BubbleNote {
- id : bubbleNote
- visible : false
- Component.onCompleted : {
- bubbleNote.place(0)
- }
- }
-
- BubbleNote {
- id:addAccountTip
- anchors.topMargin: viewAccount.separatorNoAccount - 2*Style.main.fontSize
- text : qsTr("Click here to start", "on first launch, this is displayed above the Add Account button to tell the user what to do first")
- state: (go.isFirstStart && viewAccount.numAccounts==0 && root.viewContent.currentIndex==0) ? "Visible" : "Invisible"
- bubbleColor: Style.main.textBlue
-
- Component.onCompleted : {
- addAccountTip.place(-1)
- }
- enabled: false
-
- states: [
- State {
- name: "Visible"
- // hack: opacity 100% makes buttons dialog windows quit wrong color
- PropertyChanges{target: addAccountTip; opacity: 0.999; visible: true}
- },
- State {
- name: "Invisible"
- PropertyChanges{target: addAccountTip; opacity: 0.0; visible: false}
- }
- ]
-
- transitions: [
- Transition {
- from: "Visible"
- to: "Invisible"
-
- SequentialAnimation{
- NumberAnimation {
- target: addAccountTip
- property: "opacity"
- duration: 0
- easing.type: Easing.InOutQuad
- }
- NumberAnimation {
- target: addAccountTip
- property: "visible"
- duration: 0
- }
- }
- },
- Transition {
- from: "Invisible"
- to: "Visible"
- SequentialAnimation{
- NumberAnimation {
- target: addAccountTip
- property: "visible"
- duration: 300
- }
- NumberAnimation {
- target: addAccountTip
- property: "opacity"
- duration: 500
- easing.type: Easing.InOutQuad
- }
- }
- }
- ]
- }
-
-
- // Dialogs
-
- DialogAddUser {
- id: dialogAddUser
-
- anchors {
- top : infoBar.bottom
- bottomMargin: innerWindowBorder
- leftMargin: innerWindowBorder
- rightMargin: innerWindowBorder
- }
-
- onCreateAccount: Qt.openUrlExternally("https://protonmail.com/signup")
- }
-
- DialogUpdate {
- id: dialogUpdate
- forceUpdate: root.isOutdateVersion
- }
-
-
- DialogExport {
- id: dialogExport
- anchors {
- top : infoBar.bottom
- bottomMargin: innerWindowBorder
- leftMargin: innerWindowBorder
- rightMargin: innerWindowBorder
- }
-
- }
-
- DialogImport {
- id: dialogImport
- anchors {
- top : infoBar.bottom
- bottomMargin: innerWindowBorder
- leftMargin: innerWindowBorder
- rightMargin: innerWindowBorder
- }
-
- }
-
- Dialog {
- id: dialogCredits
- anchors {
- top : infoBar.bottom
- bottomMargin: innerWindowBorder
- leftMargin: innerWindowBorder
- rightMargin: innerWindowBorder
- }
-
- title: qsTr("Credits", "title for list of credited libraries")
-
- Credits { }
- }
-
- DialogYesNo {
- id: dialogGlobal
- question : ""
- answer : ""
- z: 100
- }
-
- PopupEditFolder {
- id: popupFolderEdit
- anchors {
- left: parent.left
- right: parent.right
- top: infoBar.bottom
- bottom: parent.bottom
- }
- }
-
- // Popup
- PopupMessage {
- id: popupMessage
- anchors {
- left : parent.left
- right : parent.right
- top : infoBar.bottom
- bottom : parent.bottom
- }
-
- onClickedNo: popupMessage.hide()
- onClickedOkay: popupMessage.hide()
- onClickedCancel: popupMessage.hide()
- onClickedYes: {
- if (popupMessage.text == gui.areYouSureYouWantToQuit) Qt.quit()
- }
- }
-
- // resize
- MouseArea { // bottom
- id: resizeBottom
- property int diff: 0
- anchors {
- bottom : parent.bottom
- left : parent.left
- right : parent.right
- }
- cursorShape: Qt.SizeVerCursor
- height: Style.main.fontSize
- onPressed: {
- var globPos = mapToGlobal(mouse.x, mouse.y)
- resizeBottom.diff = root.height
- resizeBottom.diff -= globPos.y
- }
- onMouseYChanged : {
- var globPos = mapToGlobal(mouse.x, mouse.y)
- root.height = Math.max(root.minimumHeight, globPos.y + resizeBottom.diff)
- }
- }
-
- MouseArea { // right
- id: resizeRight
- property int diff: 0
- anchors {
- top : titleBar.bottom
- bottom : parent.bottom
- right : parent.right
- }
- cursorShape: Qt.SizeHorCursor
- width: Style.main.fontSize/2
- onPressed: {
- var globPos = mapToGlobal(mouse.x, mouse.y)
- resizeRight.diff = root.width
- resizeRight.diff -= globPos.x
- }
- onMouseXChanged : {
- var globPos = mapToGlobal(mouse.x, mouse.y)
- root.width = Math.max(root.minimumWidth, globPos.x + resizeRight.diff)
- }
- }
-
- function showAndRise(){
- go.loadAccounts()
- root.show()
- root.raise()
- if (!root.active) {
- root.requestActivate()
- }
- }
-
- // Toggle window
- function toggle() {
- go.loadAccounts()
- if (root.visible) {
- if (!root.active) {
- root.raise()
- root.requestActivate()
- } else {
- root.hide()
- }
- } else {
- root.show()
- root.raise()
- }
- }
-
- onClosing : {
- close.accepted=false
- if (
- (dialogImport.visible && dialogImport.currentIndex == 4 && go.progress!=1) ||
- (dialogExport.visible && dialogExport.currentIndex == 2 && go.progress!=1)
- ) {
- popupMessage.buttonOkay .visible = false
- popupMessage.buttonYes .visible = false
- popupMessage.buttonQuit .visible = true
- popupMessage.buttonCancel .visible = true
- popupMessage.show ( gui.areYouSureYouWantToQuit )
- return
- }
-
- close.accepted=true
- go.processFinished()
- }
-}
diff --git a/internal/frontend/qml/ImportExportUI/OutputFormat.qml b/internal/frontend/qml/ImportExportUI/OutputFormat.qml
deleted file mode 100644
index b5da7db9..00000000
--- a/internal/frontend/qml/ImportExportUI/OutputFormat.qml
+++ /dev/null
@@ -1,84 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-import QtQuick 2.8
-import QtQuick.Controls 2.2
-import ProtonUI 1.0
-import ImportExportUI 1.0
-
-Column {
- spacing: Style.dialog.spacing
- property string checkedText : group.checkedButton.text
-
- Text {
- id: formatLabel
- font {
- pointSize: Style.dialog.fontSize * Style.pt
- bold: true
- }
- color: Style.dialog.text
- text: qsTr("Select format of exported email:")
-
- InfoToolTip {
- info: qsTr("MBOX exports one file for each folder", "todo") + "\n" + qsTr("EML exports one file for each email", "todo")
- anchors {
- left: parent.right
- leftMargin: Style.dialog.spacing
- verticalCenter: parent.verticalCenter
- }
- }
- }
-
- Row {
- spacing : Style.main.leftMargin
- ButtonGroup {
- id: group
- }
-
- Repeater {
- model: [ "MBOX", "EML" ]
- delegate : RadioButton {
- id: radioDelegate
- checked: modelData=="MBOX"
- width: 5*Style.dialog.fontSize // hack due to bold
- text: modelData
- ButtonGroup.group: group
- spacing: Style.main.spacing
- indicator: Text {
- text : radioDelegate.checked ? Style.fa.check_circle : Style.fa.circle_o
- color : radioDelegate.checked ? Style.main.textBlue : Style.main.textInactive
- font {
- pointSize: Style.dialog.iconSize * Style.pt
- family: Style.fontawesome.name
- }
- anchors.verticalCenter: parent.verticalCenter
- }
- contentItem: Text {
- text: radioDelegate.text
- color: Style.main.text
- font {
- pointSize: Style.dialog.fontSize * Style.pt
- bold: checked
- }
- horizontalAlignment : Text.AlignHCenter
- verticalAlignment : Text.AlignVCenter
- leftPadding: Style.dialog.iconSize
- }
- }
- }
- }
-}
diff --git a/internal/frontend/qml/ImportExportUI/PopupEditFolder.qml b/internal/frontend/qml/ImportExportUI/PopupEditFolder.qml
deleted file mode 100644
index 64574020..00000000
--- a/internal/frontend/qml/ImportExportUI/PopupEditFolder.qml
+++ /dev/null
@@ -1,311 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// popup to edit folders or labels
-import QtQuick 2.8
-import QtQuick.Controls 2.1
-import ImportExportUI 1.0
-import ProtonUI 1.0
-
-
-Rectangle {
- id: root
- visible: false
- color: "#aa223344"
-
- property string folderType : gui.enums.folderTypeFolder
- property bool isFolder : folderType == gui.enums.folderTypeFolder
- property bool isNew : currentId == ""
- property bool isCreateLater : currentId == "createLater" // NOTE: "createLater" is hack because folder id should be base64 string
-
- property string currentName : ""
- property string currentId : ""
- property string currentColor : ""
-
- property string sourceID : ""
- property string selectedColor : colorList[0]
-
- property color textColor : Style.main.background
- property color backColor : Style.bubble.paneBackground
-
- signal edited(string newName, string newColor)
-
-
-
-
- property var colorList : [ "#7272a7", "#8989ac", "#cf5858", "#cf7e7e", "#c26cc7", "#c793ca", "#7569d1", "#9b94d1", "#69a9d1", "#a8c4d5", "#5ec7b7", "#97c9c1", "#72bb75", "#9db99f", "#c3d261", "#c6cd97", "#e6c04c", "#e7d292", "#e6984c", "#dfb286" ]
-
- MouseArea { // prevent action below aka modal: true
- anchors.fill: parent
- hoverEnabled: true
- }
-
- Rectangle {
- id:background
-
- anchors {
- fill: root
- leftMargin: winMain.width/6
- topMargin: winMain.height/6
- rightMargin: anchors.leftMargin
- bottomMargin: anchors.topMargin
- }
-
- color: backColor
- radius: Style.errorDialog.radius
- }
-
-
- Column { // content
- anchors {
- top : background.top
- horizontalCenter : background.horizontalCenter
- }
-
- topPadding : Style.main.topMargin
- bottomPadding : topPadding
- spacing : (background.height - title.height - inputField.height - view.height - buttonRow.height - topPadding - bottomPadding) / children.length
-
- Text {
- id: title
-
- font.pointSize: Style.dialog.titleSize * Style.pt
- color: textColor
-
- text: {
- if ( root.isFolder && root.isNew ) return qsTr ( "Create new folder" )
- if ( !root.isFolder && root.isNew ) return qsTr ( "Create new label" )
- if ( root.isFolder && !root.isNew ) return qsTr ( "Edit folder %1" ) .arg( root.currentName )
- if ( !root.isFolder && !root.isNew ) return qsTr ( "Edit label %1" ) .arg( root.currentName )
- }
-
- width : parent.width
- elide : Text.ElideRight
-
- horizontalAlignment : Text.AlignHCenter
-
- Rectangle {
- anchors {
- top: parent.bottom
- topMargin: Style.dialog.spacing
- horizontalCenter: parent.horizontalCenter
- }
- color: textColor
- height: Style.main.borderInput
- }
- }
-
- TextField {
- id: inputField
-
- anchors {
- horizontalCenter: parent.horizontalCenter
- }
-
- width : parent.width
- height : Style.dialog.button
- rightPadding : Style.dialog.spacing
- leftPadding : height + rightPadding
- bottomPadding : rightPadding
- topPadding : rightPadding
- selectByMouse : true
- color : textColor
- font.pointSize : Style.dialog.fontSize * Style.pt
-
- background: Rectangle {
- color: backColor
- border {
- color: textColor
- width: Style.dialog.borderInput
- }
-
- radius : Style.dialog.radiusButton
-
- Text {
- anchors {
- left: parent.left
- verticalCenter: parent.verticalCenter
- }
-
- font {
- family: Style.fontawesome.name
- pointSize: Style.dialog.titleSize * Style.pt
- }
-
- text : folderType == gui.enums.folderTypeFolder ? Style.fa.folder : Style.fa.tag
- color : root.selectedColor
- width : parent.height
- horizontalAlignment: Text.AlignHCenter
- }
-
- Rectangle {
- anchors {
- left: parent.left
- top: parent.top
- leftMargin: parent.height
- }
- width: parent.border.width/2
- height: parent.height
- }
- }
- }
-
-
- GridView {
- id: view
-
- anchors {
- horizontalCenter: parent.horizontalCenter
- }
-
- model : colorList
- cellWidth : 2*Style.dialog.titleSize
- cellHeight : cellWidth
- width : 10*cellWidth
- height : 2*cellHeight
-
- delegate: Rectangle {
- width: view.cellWidth*0.8
- height: width
- radius: width/2
- color: modelData
-
- border {
- color: indicator.visible ? textColor : modelData
- width: 2*Style.px
- }
-
- Text {
- id: indicator
- anchors.centerIn : parent
- text: Style.fa.check
- color: textColor
- font {
- family: Style.fontawesome.name
- pointSize: Style.dialog.titleSize * Style.pt
- }
- visible: modelData == root.selectedColor
- }
-
- MouseArea {
- anchors.fill: parent
- onClicked : {
- root.selectedColor = modelData
- }
- }
- }
- }
-
- Row {
- id: buttonRow
-
- anchors {
- horizontalCenter: parent.horizontalCenter
- }
-
- spacing: Style.main.leftMargin
-
- ButtonRounded {
- text: "Cancel"
- color_main : textColor
- onClicked :{
- root.hide()
- }
- }
-
- ButtonRounded {
- text: "Okay"
- color_main: Style.dialog.background
- color_minor: Style.dialog.textBlue
- isOpaque: true
- onClicked :{
- root.okay()
- }
- }
- }
- }
-
- function hide() {
- root.visible=false
- root.currentId = ""
- root.currentName = ""
- root.currentColor = ""
- root.folderType = ""
- root.sourceID = ""
- inputField.text = ""
- }
-
- function show(currentName, currentId, currentColor, folderType, sourceID) {
- root.currentId = currentId
- root.currentName = currentName
- root.currentColor = currentColor=="" ? go.leastUsedColor() : currentColor
- root.selectedColor = root.currentColor
- root.folderType = folderType
- root.sourceID = sourceID
-
- inputField.text = currentName
- root.visible=true
- //console.log(title.text , root.currentName, root.currentId, root.currentColor, root.folderType, root.sourceID)
- }
-
- function okay() {
- // check inpupts
- if (inputField.text == "") {
- go.notifyError(gui.enums.errFillFolderName)
- return
- }
- if (colorList.indexOf(root.selectedColor)<0) {
- go.notifyError(gui.enums.errSelectFolderColor)
- return
- }
- var isLabel = root.folderType == gui.enums.folderTypeLabel
- if (!isLabel && !root.isFolder){
- console.log("Unknown folder type: ", root.folderType)
- go.notifyError(gui.enums.errUpdateLabelFailed)
- root.hide()
- return
- }
-
- if (winMain.dialogImport.address == "") {
- console.log("Unknown address", winMain.dialogImport.address)
- go.onNotifyError(gui.enums.errUpdateLabelFailed)
- root.hide()
- }
-
- if (root.isCreateLater) {
- root.edited(inputField.text, root.selectedColor)
- root.hide()
- return
- }
-
-
- // TODO send request (as timer)
- if (root.isNew) {
- var isOK = go.createLabelOrFolder(winMain.dialogImport.address, inputField.text, root.selectedColor, isLabel, root.sourceID)
- if (isOK) {
- root.hide()
- }
- } else {
- // TODO: check there was some change
- go.updateLabelOrFolder(winMain.dialogImport.address, root.currentId, inputField.text, root.selectedColor)
- }
-
- // waiting for finish
- // TODO: waiting wheel of doom
- // TODO: on close add source to sourceID
- }
-}
diff --git a/internal/frontend/qml/ImportExportUI/SelectFolderMenu.qml b/internal/frontend/qml/ImportExportUI/SelectFolderMenu.qml
deleted file mode 100644
index 0d881d56..00000000
--- a/internal/frontend/qml/ImportExportUI/SelectFolderMenu.qml
+++ /dev/null
@@ -1,355 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// This is global combo box which can be adjusted to choose folder target, folder label or global label
-import QtQuick 2.8
-import QtQuick.Controls 2.2
-import ProtonUI 1.0
-import ImportExportUI 1.0
-
-ComboBox {
- id: root
- //fixme rounded
- height: Style.main.fontSize*2 //fixme
- property string folderType: gui.enums.folderTypeFolder
- property string sourceID
- property var targets
- property bool isFolderType: root.folderType == gui.enums.folderTypeFolder
- property bool below: true
-
- signal doNotImport()
- signal importToFolder(string newTargetID)
- signal addTargetLabel(string newTargetID)
- signal removeTargetLabel(string newTargetID)
-
- leftPadding: Style.dialog.spacing
-
- onDownChanged : {
- root.below = popup.y>0
- }
-
- contentItem : Row {
- id: boxText
-
- Text {
- anchors.verticalCenter: parent.verticalCenter
- font {
- pointSize: Style.dialog.fontSize * Style.pt
- family: Style.fontawesome.name
- }
- text: {
- if (view.currentIndex >= 0) {
- if (!root.isFolderType) {
- return Style.fa.tags + " "
- }
- var tgtIcon = view.currentItem.folderIcon
- var tgtColor = view.currentItem.folderColor
- if (tgtIcon != Style.fa.folder_open) {
- return tgtIcon + " "
- }
- return ''+ tgtIcon + " "
- }
- return ""
- }
- color: !root.enabled ? Style.main.textDisabled : ( root.down ? Style.main.background : Style.main.text )
- }
-
- Text {
- anchors.verticalCenter: parent.verticalCenter
- font {
- pointSize : Style.dialog.fontSize * Style.pt
- bold: root.down
- }
- elide: Text.ElideRight
- textFormat: Text.StyledText
-
- text : root.displayText
- color: !root.enabled ? Style.main.textDisabled : ( root.down ? Style.main.background : Style.main.text )
- }
- }
-
- displayText: {
- if (view.currentIndex >= 0) {
- if (!root.isFolderType) return qsTr("Add/Remove labels")
- return view.currentItem.folderName
- }
- if (root.isFolderType) return qsTr("No folder selected")
- return qsTr("No labels selected")
- }
-
-
- background : RoundedRectangle {
- fillColor : root.down ? Style.main.textBlue : Style.transparent
- strokeColor : root.down ? fillColor : Style.main.line
- radiusTopLeft : root.down && !root.below ? 0 : Style.dialog.radiusButton
- radiusBottomLeft : root.down && root.below ? 0 : Style.dialog.radiusButton
- radiusTopRight : radiusTopLeft
- radiusBottomRight : radiusBottomLeft
-
- MouseArea {
- anchors.fill: parent
- onClicked : {
- if (root.down) root.popup.close()
- else root.popup.open()
- }
- }
- }
-
- indicator : Text {
- text: (root.down && root.below) || (!root.down && !root.below) ? Style.fa.chevron_up : Style.fa.chevron_down
- anchors {
- right: parent.right
- verticalCenter: parent.verticalCenter
- rightMargin: Style.dialog.spacing
- }
- font {
- family : Style.fontawesome.name
- pointSize : Style.dialog.fontSize * Style.pt
- }
- color: root.enabled && !root.down ? Style.main.textBlue : root.contentItem.color
- }
-
- // Popup row
- delegate: Rectangle {
- id: thisDelegate
-
- height : Style.main.fontSize * 2
- width : selectNone.width
-
- property bool isHovered: area.containsMouse
-
- color: isHovered ? root.popup.hoverColor : root.popup.backColor
-
- property bool isSelected : isActive
- property string folderName: name
- property string folderIcon: gui.folderIcon(name,type)
- property string folderColor: (type == gui.enums.folderTypeLabel || type == gui.enums.folderTypeFolder) ? iconColor : root.popup.textColor
-
- Text {
- id: targetIcon
- text: thisDelegate.folderIcon
- color : thisDelegate.folderColor
- anchors {
- verticalCenter: parent.verticalCenter
- left: parent.left
- leftMargin: root.leftPadding
- }
- font {
- family : Style.fontawesome.name
- pointSize : Style.dialog.fontSize * Style.pt
- }
- }
-
- Text {
- id: targetName
-
-
- anchors {
- verticalCenter: parent.verticalCenter
- left: targetIcon.right
- right: parent.right
- leftMargin: Style.dialog.spacing
- rightMargin: Style.dialog.spacing
- }
-
- text: thisDelegate.folderName
- color : root.popup.textColor
- elide: Text.ElideRight
-
- font {
- family : Style.fontawesome.name
- pointSize : Style.dialog.fontSize * Style.pt
- }
- }
-
- Text {
- id: targetIndicator
- anchors {
- right: parent.right
- verticalCenter: parent.verticalCenter
- }
-
- text : thisDelegate.isSelected ? Style.fa.check_square : Style.fa.square_o
- visible : thisDelegate.isSelected || !root.isFolderType
- color : root.popup.textColor
- font {
- family : Style.fontawesome.name
- pointSize : Style.dialog.fontSize * Style.pt
- }
- }
-
- Rectangle {
- id: line
- anchors {
- bottom : parent.bottom
- left : parent.left
- right : parent.right
- }
- height : Style.main.lineWidth
- color : Style.main.line
- }
-
- MouseArea {
- id: area
- anchors.fill: parent
-
- onClicked: {
- //console.log(" click delegate")
- if (root.isFolderType) { // don't update if selected
- root.popup.close()
- if (!isActive) {
- root.importToFolder(mboxID)
- }
- } else {
- if (isActive) {
- root.removeTargetLabel(mboxID)
- } else {
- root.addTargetLabel(mboxID)
- }
- }
- }
- hoverEnabled: true
- }
- }
-
- popup : Popup {
- y: root.height
- width: root.width
- modal: true
- closePolicy: Popup.CloseOnPressOutside | Popup.CloseOnEscape
- padding: Style.dialog.spacing
-
- property var textColor : Style.main.background
- property var backColor : Style.main.text
- property var hoverColor : Style.main.textBlue
-
- contentItem : Column {
- // header
- Rectangle {
- id: selectNone
- width: root.popup.width - 2*root.popup.padding
- //height: root.isFolderType ? 2* Style.main.fontSize : 0
- height: 2*Style.main.fontSize
- color: area.containsMouse ? root.popup.hoverColor : root.popup.backColor
- visible : root.isFolderType
-
- Text {
- anchors {
- left : parent.left
- leftMargin : Style.dialog.spacing
- verticalCenter : parent.verticalCenter
- }
- text: root.isFolderType ? qsTr("Do not import") : ""
- color: root.popup.textColor
- font {
- pointSize: Style.dialog.fontSize * Style.pt
- bold: true
- }
- }
-
- Rectangle {
- id: line
- anchors {
- bottom : parent.bottom
- left : parent.left
- right : parent.right
- }
- height : Style.dialog.borderInput
- color : Style.main.line
- }
-
- MouseArea {
- id: area
- anchors.fill: parent
- onClicked: {
- //console.log(" click no set")
- root.doNotImport()
- root.popup.close()
- }
- hoverEnabled: true
- }
- }
-
- // scroll area
- Rectangle {
- width: selectNone.width
- height: winMain.height/4
- color: root.popup.backColor
-
- ListView {
- id: view
-
- clip : true
- anchors.fill : parent
- model : root.targets
- delegate : root.delegate
-
- currentIndex: view.model.selectedIndex
- }
- }
-
- // footer
- Rectangle {
- id: addFolderOrLabel
- width: selectNone.width
- height: addButton.height + 3*Style.dialog.spacing
- color: root.popup.backColor
-
- Rectangle {
- anchors {
- top : parent.top
- left : parent.left
- right : parent.right
- }
- height : Style.dialog.borderInput
- color : Style.main.line
- }
-
- ButtonRounded {
- id: addButton
- anchors.centerIn: addFolderOrLabel
- width: parent.width * 0.681
-
- fa_icon : Style.fa.plus_circle
- text : root.isFolderType ? qsTr("Create new folder") : qsTr("Create new label")
- color_main : root.popup.textColor
- }
-
- MouseArea {
- anchors.fill : parent
-
- onClicked : {
- //console.log("click", addButton.text)
- var newName = name
- winMain.popupFolderEdit.show(newName, "", "", root.folderType, sourceID)
- root.popup.close()
- }
- }
- }
- }
-
- background : RoundedRectangle {
- strokeColor : root.popup.backColor
- fillColor : root.popup.backColor
- radiusTopLeft : root.below ? 0 : Style.dialog.radiusButton
- radiusBottomLeft : !root.below ? 0 : Style.dialog.radiusButton
- radiusTopRight : radiusTopLeft
- radiusBottomRight : radiusBottomLeft
- }
- }
-}
-
diff --git a/internal/frontend/qml/ImportExportUI/SelectLabelsMenu.qml b/internal/frontend/qml/ImportExportUI/SelectLabelsMenu.qml
deleted file mode 100644
index c8205a26..00000000
--- a/internal/frontend/qml/ImportExportUI/SelectLabelsMenu.qml
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// List of import folder and their target
-import QtQuick 2.8
-import QtQuick.Controls 2.2
-import ProtonUI 1.0
-import ImportExportUI 1.0
-
-SelectFolderMenu {
- id: root
- folderType: gui.enums.folderTypeLabel
-}
-
-
diff --git a/internal/frontend/qml/ImportExportUI/SettingsView.qml b/internal/frontend/qml/ImportExportUI/SettingsView.qml
deleted file mode 100644
index 6a5be439..00000000
--- a/internal/frontend/qml/ImportExportUI/SettingsView.qml
+++ /dev/null
@@ -1,189 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// List the settings
-
-import QtQuick 2.8
-import ProtonUI 1.0
-import ImportExportUI 1.0
-import QtQuick.Controls 2.4
-
-Item {
- id: root
-
- // must have wrapper
- ScrollView {
- id: wrapper
- anchors.centerIn: parent
- width: parent.width
- height: parent.height
- background: Rectangle {
- color: Style.main.background
- }
-
- // horizontall scrollbar sometimes showes up when vertical scrollbar coveres content
- ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
- ScrollBar.vertical.policy: ScrollBar.AsNeeded
-
- // keeping vertical scrollbar allways visible when needed
- Connections {
- target: wrapper.ScrollBar.vertical
- onSizeChanged: {
- // ScrollBar.size == 0 at creating so no need to make it active
- if (wrapper.ScrollBar.vertical.size < 1.0 && wrapper.ScrollBar.vertical.size > 0 && !wrapper.ScrollBar.vertical.active) {
- wrapper.ScrollBar.vertical.active = true
- }
- }
- onActiveChanged: {
- wrapper.ScrollBar.vertical.active = true
- }
- }
-
- // content
- Column {
- anchors.left : parent.left
-
- ButtonIconText {
- id: cacheKeychain
- text: qsTr("Clear Keychain")
- leftIcon.text : Style.fa.chain_broken
- rightIcon {
- text : qsTr("Clear")
- color: Style.main.text
- font {
- family : cacheKeychain.font.family // use default font, not font-awesome
- pointSize : Style.settings.fontSize * Style.pt
- underline : true
- }
- }
- onClicked: {
- dialogGlobal.state="clearChain"
- dialogGlobal.show()
- }
- }
-
- ButtonIconText {
- id: logs
- anchors.left: parent.left
- text: qsTr("Logs")
- leftIcon.text : Style.fa.align_justify
- rightIcon.text : Style.fa.chevron_circle_right
- rightIcon.font.pointSize : Style.settings.toggleSize * Style.pt
- onClicked: go.openLogs()
- }
-
- ButtonIconText {
- id: bugreport
- anchors.left: parent.left
- text: qsTr("Report Bug")
- leftIcon.text : Style.fa.bug
- rightIcon.text : Style.fa.chevron_circle_right
- rightIcon.font.pointSize : Style.settings.toggleSize * Style.pt
- onClicked: bugreportWin.show()
- }
-
- /*
-
- ButtonIconText {
- id: autoUpdates
- text: qsTr("Keep the application up to date", "label for toggle that activates and disables the automatic updates")
- leftIcon.text : Style.fa.download
- rightIcon {
- font.pointSize : Style.settings.toggleSize * Style.pt
- text : go.isAutoUpdate!=false ? Style.fa.toggle_on : Style.fa.toggle_off
- color : go.isAutoUpdate!=false ? Style.main.textBlue : Style.main.textDisabled
- }
- Accessible.description: (
- go.isAutoUpdate == false ?
- qsTr("Enable" , "Click to enable the automatic update of Bridge") :
- qsTr("Disable" , "Click to disable the automatic update of Bridge")
- ) + " " + text
- onClicked: {
- go.toggleAutoUpdate()
- }
- }
-
- ButtonIconText {
- id: cacheClear
- text: qsTr("Clear Cache")
- leftIcon.text : Style.fa.times
- rightIcon {
- text : qsTr("Clear")
- color: Style.main.text
- font {
- pointSize : Style.settings.fontSize * Style.pt
- underline : true
- }
- }
- onClicked: {
- dialogGlobal.state="clearCache"
- dialogGlobal.show()
- }
- }
-
-
- ButtonIconText {
- id: autoStart
- text: qsTr("Automatically Start Bridge")
- leftIcon.text : Style.fa.rocket
- rightIcon {
- font.pointSize : Style.settings.toggleSize * Style.pt
- text : go.isAutoStart!=0 ? Style.fa.toggle_on : Style.fa.toggle_off
- color : go.isAutoStart!=0 ? Style.main.textBlue : Style.main.textDisabled
- }
- onClicked: {
- go.toggleAutoStart()
- }
- }
-
- ButtonIconText {
- id: advancedSettings
- property bool isAdvanced : !go.isDefaultPort
- text: qsTr("Advanced settings")
- leftIcon.text : Style.fa.cogs
- rightIcon {
- font.pointSize : Style.settings.toggleSize * Style.pt
- text : isAdvanced!=0 ? Style.fa.chevron_circle_up : Style.fa.chevron_circle_right
- color : isAdvanced!=0 ? Style.main.textDisabled : Style.main.textBlue
- }
- onClicked: {
- isAdvanced = !isAdvanced
- }
- }
-
- ButtonIconText {
- id: changePort
- visible: advancedSettings.isAdvanced
- text: qsTr("Change SMTP/IMAP Ports")
- leftIcon.text : Style.fa.plug
- rightIcon {
- text : qsTr("Change")
- color: Style.main.text
- font {
- pointSize : Style.settings.fontSize * Style.pt
- underline : true
- }
- }
- onClicked: {
- dialogChangePort.show()
- }
- }
- */
- }
- }
-}
-
diff --git a/internal/frontend/qml/ImportExportUI/qmldir b/internal/frontend/qml/ImportExportUI/qmldir
deleted file mode 100644
index 752ffc16..00000000
--- a/internal/frontend/qml/ImportExportUI/qmldir
+++ /dev/null
@@ -1,31 +0,0 @@
-module ImportExportUI
-AccountDelegate 1.0 AccountDelegate.qml
-Credits 1.0 Credits.qml
-DateBox 1.0 DateBox.qml
-DateInput 1.0 DateInput.qml
-DateRangeMenu 1.0 DateRangeMenu.qml
-DateRange 1.0 DateRange.qml
-DateRangeFunctions 1.0 DateRangeFunctions.qml
-DialogExport 1.0 DialogExport.qml
-DialogImport 1.0 DialogImport.qml
-DialogYesNo 1.0 DialogYesNo.qml
-ExportStructure 1.0 ExportStructure.qml
-FilterStructure 1.0 FilterStructure.qml
-FolderRowButton 1.0 FolderRowButton.qml
-HelpView 1.0 HelpView.qml
-IEStyle 1.0 IEStyle.qml
-ImportDelegate 1.0 ImportDelegate.qml
-ImportSourceButton 1.0 ImportSourceButton.qml
-ImportStructure 1.0 ImportStructure.qml
-ImportReport 1.0 ImportReport.qml
-ImportReportCell 1.0 ImportReportCell.qml
-InlineDateRange 1.0 InlineDateRange.qml
-InlineLabelSelect 1.0 InlineLabelSelect.qml
-LabelIconList 1.0 LabelIconList.qml
-MainWindow 1.0 MainWindow.qml
-OutputFormat 1.0 OutputFormat.qml
-PopupEditFolder 1.0 PopupEditFolder.qml
-SelectFolderMenu 1.0 SelectFolderMenu.qml
-SelectLabelsMenu 1.0 SelectLabelsMenu.qml
-SettingsView 1.0 SettingsView.qml
-VersionInfo 1.0 VersionInfo.qml
diff --git a/internal/frontend/qml/MainWindow.qml b/internal/frontend/qml/MainWindow.qml
new file mode 100644
index 00000000..f7e3faa6
--- /dev/null
+++ b/internal/frontend/qml/MainWindow.qml
@@ -0,0 +1,63 @@
+// Copyright (c) 2021 Proton Technologies AG
+//
+// This file is part of ProtonMail Bridge.
+//
+// ProtonMail Bridge 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.
+//
+// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
+
+import QtQuick 2.13
+import QtQuick.Window 2.15
+import Qt.labs.platform 1.0
+
+QtObject {
+
+ property var _mainWindow: Window {
+ id: mainWindow
+ title: "window 1"
+ visible: false
+ }
+
+ property var _trayMenu: Window {
+ id: trayMenu
+ title: "window 2"
+ visible: false
+ flags: Qt.Dialog
+
+ width: 448
+ }
+
+ property var _trayIcon: SystemTrayIcon {
+ id: trayIcon
+ visible: true
+ iconSource: "./icons/rectangle-systray.png"
+ onActivated: {
+ switch (reason) {
+ case SystemTrayIcon.Unknown:
+ break;
+ case SystemTrayIcon.Context:
+ break
+ case SystemTrayIcon.DoubleClick:
+ break
+ case SystemTrayIcon.Trigger:
+ trayMenu.x = (Screen.desktopAvailableWidth - trayMenu.width) / 2
+ trayMenu.visible = !trayMenu.visible
+ break;
+ case SystemTrayIcon.MiddleClick:
+ mainWindow.visible = !mainWindow.visible
+ break;
+ default:
+ break;
+ }
+ }
+ }
+}
diff --git a/internal/frontend/qml/ProtonUI/AccessibleButton.qml b/internal/frontend/qml/ProtonUI/AccessibleButton.qml
deleted file mode 100644
index 1fe8a89d..00000000
--- a/internal/frontend/qml/ProtonUI/AccessibleButton.qml
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// default options to make button accessible
-
-import QtQuick 2.8
-import QtQuick.Controls 2.1
-import ProtonUI 1.0
-
-Button {
- function clearText(value) {
- // remove font-awesome chars
- return value.replace(/[\uf000-\uf2e0]/g,'')
- }
- Accessible.onPressAction: clicked()
- Accessible.ignored: !enabled || !visible
- Accessible.name: clearText(text)
- Accessible.description: clearText(text)
-}
-
diff --git a/internal/frontend/qml/ProtonUI/AccessibleSelectableText.qml b/internal/frontend/qml/ProtonUI/AccessibleSelectableText.qml
deleted file mode 100644
index afe8a550..00000000
--- a/internal/frontend/qml/ProtonUI/AccessibleSelectableText.qml
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// default options to make text accessible and selectable
-
-import QtQuick 2.8
-import ProtonUI 1.0
-
-TextEdit {
- function clearText(value) {
- // substitue the copyright symbol by the text and remove the font-awesome chars and HTML tags
- return value.replace(/\uf1f9/g,'Copyright').replace(/[\uf000-\uf2e0]/g,'').replace(/<[^>]+>/g,'')
- }
-
- readOnly: true
- selectByKeyboard: true
- selectByMouse: true
-
- Accessible.role: Accessible.StaticText
- Accessible.name: clearText(text)
- Accessible.description: clearText(text)
- Accessible.focusable: true
- Accessible.ignored: !enabled || !visible || text == ""
-}
-
-
diff --git a/internal/frontend/qml/ProtonUI/AccessibleText.qml b/internal/frontend/qml/ProtonUI/AccessibleText.qml
deleted file mode 100644
index 1cd0c5bf..00000000
--- a/internal/frontend/qml/ProtonUI/AccessibleText.qml
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// default options to make text accessible
-
-import QtQuick 2.8
-import ProtonUI 1.0
-
-Text {
- function clearText(value) {
- // substitue the copyright symbol by the text and remove the font-awesome chars and HTML tags
- return value.replace(/\uf1f9/g,'Copyright').replace(/[\uf000-\uf2e0]/g,'').replace(/<[^>]+>/g,'')
- }
- Accessible.role: Accessible.StaticText
- Accessible.name: clearText(text)
- Accessible.description: clearText(text)
- Accessible.focusable: true
- Accessible.ignored: !enabled || !visible || text == ""
-
- MouseArea {
- anchors.fill: parent
- cursorShape: parent.hoveredLink ? Qt.PointingHandCursor : Qt.ArrowCursor
- acceptedButtons: Qt.NoButton
- }
-}
-
diff --git a/internal/frontend/qml/ProtonUI/AccountView.qml b/internal/frontend/qml/ProtonUI/AccountView.qml
deleted file mode 100644
index 67bfc6d8..00000000
--- a/internal/frontend/qml/ProtonUI/AccountView.qml
+++ /dev/null
@@ -1,140 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-import QtQuick 2.8
-import QtQuick.Controls 2.1
-import ProtonUI 1.0
-
-Item {
- id: root
-
- signal addAccount()
-
- property alias numAccounts : listAccounts.count
- property alias model : listAccounts.model
- property alias delegate : listAccounts.delegate
- property int separatorNoAccount : viewContent.height-Style.accounts.heightFooter
- property bool hasFooter : true
-
- // must have wrapper
- Rectangle {
- id: wrapper
- anchors.centerIn: parent
- width: parent.width
- height: parent.height
- color: Style.main.background
-
- // content
- ListView {
- id: listAccounts
- anchors {
- top : parent.top
- left : parent.left
- right : parent.right
- bottom : hasFooter ? addAccFooter.top : parent.bottom
- }
- orientation: ListView.Vertical
- clip: true
- cacheBuffer: 2500
- boundsBehavior: Flickable.StopAtBounds
- ScrollBar.vertical: ScrollBar {
- anchors {
- right: parent.right
- rightMargin: Style.main.rightMargin/4
- }
- width: Style.main.rightMargin/3
- Accessible.ignored: true
- }
- header: Rectangle {
- width : wrapper.width
- height : root.numAccounts!=0 ? Style.accounts.heightHeader : root.separatorNoAccount
- color : "transparent"
- AccessibleText { // Placeholder on empty
- anchors {
- centerIn: parent
- }
- visible: root.numAccounts==0
- text : qsTr("No accounts added", "displayed when there are no accounts added")
- font.pointSize : Style.main.fontSize * Style.pt
- color : Style.main.textDisabled
- }
- Text { // Account
- anchors {
- left : parent.left
- leftMargin : Style.main.leftMargin
- verticalCenter : parent.verticalCenter
- }
- visible: root.numAccounts!=0
- font.bold : true
- font.pointSize : Style.main.fontSize * Style.pt
- text : qsTr("ACCOUNT", "title of column that displays account name")
- color : Style.main.textDisabled
- }
- Text { // Status
- anchors {
- left : parent.left
- leftMargin : viewContent.width/2
- verticalCenter : parent.verticalCenter
- }
- visible: root.numAccounts!=0
- font.bold : true
- font.pointSize : Style.main.fontSize * Style.pt
- text : qsTr("STATUS", "title of column that displays connected or disconnected status")
- color : Style.main.textDisabled
- }
- Text { // Actions
- anchors {
- left : parent.left
- leftMargin : 5.5*viewContent.width/8
- verticalCenter : parent.verticalCenter
- }
- visible: root.numAccounts!=0
- font.bold : true
- font.pointSize : Style.main.fontSize * Style.pt
- text : qsTr("ACTIONS", "title of column that displays log out and log in actions for each account")
- color : Style.main.textDisabled
- }
- // line
- Rectangle {
- anchors {
- left : parent.left
- right : parent.right
- bottom : parent.bottom
- }
- visible: root.numAccounts!=0
- color: Style.accounts.line
- height: Style.accounts.heightLine
- }
- }
- }
-
-
- AddAccountBar {
- id: addAccFooter
- visible: hasFooter
- anchors {
- left : parent.left
- bottom : parent.bottom
- }
- }
- }
-
- Shortcut {
- sequence: StandardKey.SelectAll
- onActivated: root.addAccount()
- }
-}
diff --git a/internal/frontend/qml/ProtonUI/AddAccountBar.qml b/internal/frontend/qml/ProtonUI/AddAccountBar.qml
deleted file mode 100644
index 598ab7b3..00000000
--- a/internal/frontend/qml/ProtonUI/AddAccountBar.qml
+++ /dev/null
@@ -1,69 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// Bar with add account button and help
-
-import QtQuick 2.8
-import ProtonUI 1.0
-
-
-Rectangle {
- width : parent.width
- height : Style.accounts.heightFooter
- color: "transparent"
- Rectangle {
- anchors {
- top : parent.top
- left : parent.left
- right : parent.right
- }
- height: Style.accounts.heightLine
- color: Style.accounts.line
- }
- ClickIconText {
- id: buttonAddAccount
- anchors {
- left : parent.left
- leftMargin : Style.main.leftMargin
- verticalCenter : parent.verticalCenter
- }
- textColor : Style.main.textBlue
- iconText : Style.fa.plus_circle
- text : qsTr("Add Account", "begins the flow to log in to an account that is not yet listed")
- textBold : true
- onClicked : root.addAccount()
- Accessible.description: {
- if (gui.winMain!=null) {
- return text + (gui.winMain.addAccountTip.visible? ", "+gui.winMain.addAccountTip.text : "")
- }
- return buttonAddAccount.text
- }
- }
- ClickIconText {
- id: buttonHelp
- anchors {
- right : parent.right
- rightMargin : Style.main.rightMargin
- verticalCenter : parent.verticalCenter
- }
- textColor : Style.main.textDisabled
- iconText : Style.fa.question_circle
- text : qsTr("Help", "directs the user to the online user guide")
- textBold : true
- onClicked : go.openManual()
- }
-}
diff --git a/internal/frontend/qml/ProtonUI/BubbleNote.qml b/internal/frontend/qml/ProtonUI/BubbleNote.qml
deleted file mode 100644
index d8fd8002..00000000
--- a/internal/frontend/qml/ProtonUI/BubbleNote.qml
+++ /dev/null
@@ -1,171 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// Notify user
-
-import QtQuick 2.8
-import ProtonUI 1.0
-
-Rectangle {
- id: root
- property int posx // x-coordinate of triangle
- property bool isTriangleBelow
- property string text
- property alias bubbleColor: bubble.color
- anchors {
- top : tabbar.bottom
- left : tabbar.left
- leftMargin : {
- // position of bubble calculated from posx
- return Math.max(
- Style.main.leftMargin, // keep minimal left margin
- Math.min(
- root.posx - root.width/2, // fit triangle in the middle if possible
- tabbar.width - root.width - Style.main.rightMargin // keep minimal right margin
- )
- )
- }
- topMargin: 0
- }
- height : triangle.height + bubble.height
- width : bubble.width
- color : "transparent"
- visible : false
-
-
- Rectangle {
- id : triangle
- anchors {
- top : root.isTriangleBelow ? undefined : root.top
- bottom : root.isTriangleBelow ? root.bottom : undefined
- bottomMargin : 1*Style.px
- left : root.left
- leftMargin : root.posx - triangle.width/2 - root.anchors.leftMargin
- }
- width: 2*Style.tabbar.heightTriangle+2
- height: Style.tabbar.heightTriangle
- color: "transparent"
- Canvas {
- anchors.fill: parent
- rotation: root.isTriangleBelow ? 180 : 0
- onPaint: {
- var ctx = getContext("2d")
- ctx.fillStyle = bubble.color
- ctx.moveTo(0 , height)
- ctx.lineTo(width/2, 0)
- ctx.lineTo(width , height)
- ctx.closePath()
- ctx.fill()
- }
- }
- }
-
- Rectangle {
- id: bubble
- anchors {
- top: root.top
- left: root.left
- topMargin: (root.isTriangleBelow ? 0 : triangle.height)
- }
- width : mainText.contentWidth + Style.main.leftMargin + Style.main.rightMargin
- height : 2*Style.main.fontSize
- radius : Style.bubble.radius
- color : Style.bubble.background
-
- AccessibleText {
- id: mainText
- anchors {
- horizontalCenter : parent.horizontalCenter
- top: parent.top
- topMargin : Style.main.fontSize
- }
-
- text: ""+root.text+""
- width : Style.bubble.width - ( Style.main.leftMargin + Style.main.rightMargin )
- font.pointSize: Style.main.fontSize * Style.pt
- horizontalAlignment: Text.AlignHCenter
- textFormat: Text.RichText
- wrapMode: Text.WordWrap
- color: Style.bubble.text
- onLinkActivated: {
- Qt.openUrlExternally(link)
- }
- MouseArea {
- anchors.fill: mainText
- cursorShape: mainText.hoveredLink ? Qt.PointingHandCursor : Qt.ArrowCursor
- acceptedButtons: Qt.NoButton
- }
-
- Accessible.name: qsTr("Message")
- Accessible.description: root.text
- }
-
- ButtonRounded {
- id: okButton
- visible: !root.isTriangleBelow
- anchors {
- bottom : parent.bottom
- horizontalCenter : parent.horizontalCenter
- bottomMargin : Style.main.fontSize
- }
- text: qsTr("Okay", "confirms and dismisses a notification")
- height: Style.main.fontSize*2
- color_main: Style.main.text
- color_minor: Style.main.textBlue
- isOpaque: true
- onClicked: hide()
- }
- }
-
- function place(index) {
- if (index < 0) {
- // add accounts
- root.isTriangleBelow = true
- bubble.height = 3.25*Style.main.fontSize
- root.posx = 2*Style.main.leftMargin
- bubble.width = mainText.contentWidth - Style.main.leftMargin
- } else {
- root.isTriangleBelow = false
- bubble.height = (
- bubble.anchors.topMargin + // from top
- mainText.contentHeight + // the text content
- Style.main.fontSize + // gap between button
- okButton.height + okButton.anchors.bottomMargin // from bottom and button
- )
- if (index < 3) {
- // possition accordig to top tab
- var margin = Style.main.leftMargin + Style.tabbar.widthButton/2
- root.posx = margin + index*tabbar.spacing
- } else {
- // quit button
- root.posx = tabbar.width - 2*Style.main.rightMargin
- }
- }
- }
-
- function show() {
- root.visible=true
- gui.winMain.activeContent = false
- }
-
- function hide() {
- root.visible=false
- go.bubbleClosed()
- gui.winMain.activeContent = true
- gui.winMain.tabbar.focusButton()
- }
-}
diff --git a/internal/frontend/qml/ProtonUI/BugReportWindow.qml b/internal/frontend/qml/ProtonUI/BugReportWindow.qml
deleted file mode 100644
index 6f5c8f3d..00000000
--- a/internal/frontend/qml/ProtonUI/BugReportWindow.qml
+++ /dev/null
@@ -1,356 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// Window for sending a bug report
-
-import QtQuick 2.8
-import QtQuick.Window 2.2
-import QtQuick.Controls 2.1
-import ProtonUI 1.0
-import QtGraphicalEffects 1.0
-
-Window {
- id:root
- property alias userAddress : userAddress
- property alias clientVersion : clientVersion
-
- width : Style.bugreport.width
- height : Style.bugreport.height
- minimumWidth : Style.bugreport.width
- maximumWidth : Style.bugreport.width
- minimumHeight : Style.bugreport.height
- maximumHeight : Style.bugreport.height
-
- property color inputBorderColor : Style.main.text
-
- color : "transparent"
- flags : Qt.Window | Qt.Dialog | Qt.FramelessWindowHint
- title : "Bug report"
- visible : false
-
- WindowTitleBar {
- id: titleBar
- window: root
- }
-
- Rectangle {
- id:background
- color: Style.main.background
- anchors {
- left : parent.left
- right : parent.right
- top : titleBar.bottom
- bottom : parent.bottom
- }
- border {
- width: Style.main.border
- color: Style.tabbar.background
- }
- }
-
- Rectangle {
- id:content
- anchors {
- fill : parent
- leftMargin : Style.main.leftMargin
- rightMargin : Style.main.rightMargin
- bottomMargin : Style.main.rightMargin
- topMargin : Style.main.rightMargin + titleBar.height
- }
- color: "transparent"
-
- // Description in flickable
- Flickable {
- id: descripWrapper
- anchors {
- left: parent.left
- right: parent.right
- top: parent.top
- }
- height: content.height - (
- (clientVersion.visible ? clientVersion.height + Style.dialog.fontSize : 0) +
- userAddress.height + Style.dialog.fontSize +
- securityNoteText.contentHeight + Style.dialog.fontSize +
- cancelButton.height + Style.dialog.fontSize
- )
- clip: true
- contentWidth : width
- contentHeight : height
-
- TextArea.flickable: TextArea {
- id: description
- focus: true
- wrapMode: TextEdit.Wrap
- placeholderText: qsTr ("Please briefly describe the bug(s) you have encountered...", "bug report instructions")
- background : Rectangle {
- color : Style.dialog.background
- radius: Style.dialog.radiusButton
- border {
- color : root.inputBorderColor
- width : Style.dialog.borderInput
- }
-
- layer.enabled: true
- layer.effect: FastBlur {
- anchors.fill: parent
- radius: 8 * Style.px
- }
- }
- color: Style.main.text
- font.pointSize: Style.dialog.fontSize * Style.pt
- selectionColor: Style.main.textBlue
- selectByKeyboard: true
- selectByMouse: true
- KeyNavigation.tab: clientVersion
- KeyNavigation.priority: KeyNavigation.BeforeItem
- }
-
- ScrollBar.vertical : ScrollBar{}
- }
-
- // Client
- TextLabel {
- anchors {
- left: parent.left
- top: descripWrapper.bottom
- topMargin: Style.dialog.fontSize
- }
- visible: clientVersion.visible
- width: parent.width/2.618
- text: qsTr ("Email client:", "in the bug report form, which third-party email client is being used")
- font.pointSize: Style.dialog.fontSize * Style.pt
- }
-
- TextField {
- id: clientVersion
- anchors {
- right: parent.right
- top: descripWrapper.bottom
- topMargin: Style.dialog.fontSize
- }
- placeholderText: qsTr("e.g. Thunderbird", "in the bug report form, placeholder text for email client")
- width: parent.width/1.618
-
- color : Style.dialog.text
- selectionColor : Style.main.textBlue
- selectByMouse : true
- font.pointSize : Style.dialog.fontSize * Style.pt
- padding : Style.dialog.radiusButton
-
- background: Rectangle {
- color : Style.dialog.background
- radius: Style.dialog.radiusButton
- border {
- color : root.inputBorderColor
- width : Style.dialog.borderInput
- }
-
- layer.enabled: true
- layer.effect: FastBlur {
- anchors.fill: parent
- radius: 8 * Style.px
- }
- }
- onAccepted: userAddress.focus = true
- }
-
- // Address
- TextLabel {
- anchors {
- left: parent.left
- top: clientVersion.visible ? clientVersion.bottom : descripWrapper.bottom
- topMargin: Style.dialog.fontSize
- }
- color: Style.dialog.text
- width: parent.width/2.618
- text: qsTr ("Contact email:", "in the bug report form, an email to contact the user at")
- font.pointSize: Style.dialog.fontSize * Style.pt
- }
-
- TextField {
- id: userAddress
- anchors {
- right: parent.right
- top: clientVersion.visible ? clientVersion.bottom : descripWrapper.bottom
- topMargin: Style.dialog.fontSize
- }
- placeholderText: "benjerry@protonmail.com"
- width: parent.width/1.618
-
- color : Style.dialog.text
- selectionColor : Style.main.textBlue
- selectByMouse : true
- font.pointSize : Style.dialog.fontSize * Style.pt
- padding : Style.dialog.radiusButton
-
- background: Rectangle {
- color : Style.dialog.background
- radius: Style.dialog.radiusButton
- border {
- color : root.inputBorderColor
- width : Style.dialog.borderInput
- }
-
- layer.enabled: true
- layer.effect: FastBlur {
- anchors.fill: parent
- radius: 8 * Style.px
- }
- }
- onAccepted: root.submit()
- }
-
- // Note
- Row {
- id: securityNote
- anchors {
- left: parent.left
- right: parent.right
- top: userAddress.bottom
- topMargin: Style.dialog.fontSize
- }
-
- Text {
- id: securityNoteIcon
- font {
- pointSize : Style.dialog.fontSize * Style.pt
- family : Style.fontawesome.name
- }
- color: Style.dialog.text
- text : Style.fa.exclamation_triangle
- }
-
- AccessibleText {
- id: securityNoteText
- anchors {
- left: securityNoteIcon.right
- leftMargin: 5 * Style.pt
- right: parent.right
- }
- wrapMode: Text.Wrap
- color: Style.dialog.text
- font.pointSize : Style.dialog.fontSize * Style.pt
- text:
- qsTr("Bug reports are not end-to-end encrypted!", "The first part of warning in bug report form") + " " +
- qsTr("Please do not send any sensitive information.", "The second part of warning in bug report form") + " " +
- qsTr("Contact us at security@protonmail.com for critical security issues.", "The third part of warning in bug report form")
- }
- }
-
- // buttons
- ButtonRounded {
- id: cancelButton
- anchors {
- left: parent.left
- bottom: parent.bottom
- }
- fa_icon: Style.fa.times
- text: qsTr ("Cancel", "dismisses current action")
- onClicked : root.hide()
- }
- ButtonRounded {
- anchors {
- right: parent.right
- bottom: parent.bottom
- }
- isOpaque: true
- color_main: "white"
- color_minor: Style.main.textBlue
- fa_icon: Style.fa.send
- text: qsTr ("Send", "button sends bug report")
- onClicked : root.submit()
- }
- }
-
- Rectangle {
- id: notification
- property bool isOK: true
- visible: false
- color: background.color
- anchors.fill: background
-
- Text {
- anchors.centerIn: parent
- color: Style.dialog.text
- width: background.width*0.6180
- text: notification.isOK ?
- qsTr ( "Bug report successfully sent." , "notification message about bug sending" ) :
- qsTr ( "Unable to submit bug report." , "notification message about bug sending" )
- horizontalAlignment: Text.AlignHCenter
- font.pointSize: Style.dialog.titleSize * Style.pt
- }
-
- Timer {
- id: notificationTimer
- interval: 3000
- repeat: false
- onTriggered : {
- notification.visible=false
- if (notification.isOK) root.hide()
- }
- }
- }
-
- function submit(){
- if(root.areInputsOK()){
- root.notify(go.sendBug(description.text, clientVersion.text, userAddress.text ))
- }
- }
-
- function isEmpty(input){
- if (input.text=="") {
- input.focus=true
- input.placeholderText = qsTr("Field required", "a field that must be filled in to submit form")
- return true
- }
- return false
- }
-
- function areInputsOK() {
- var isOK = true
- if (isEmpty(userAddress)) { isOK=false }
- if (clientVersion.visible && isEmpty(clientVersion)) { isOK=false }
- if (isEmpty(description)) { isOK=false }
- return isOK
- }
-
- function clear() {
- description.text = ""
- clientVersion.text = ""
- notification.visible = false
- }
-
- signal prefill()
-
- function notify(isOK){
- notification.isOK = isOK
- notification.visible = true
- notificationTimer.start()
- }
-
-
- function show() {
- prefill()
- description.focus=true
- root.visible=true
- }
-
- function hide() {
- clear()
- root.visible=false
- }
-}
diff --git a/internal/frontend/qml/ProtonUI/ButtonIconText.qml b/internal/frontend/qml/ProtonUI/ButtonIconText.qml
deleted file mode 100644
index 6ea9afed..00000000
--- a/internal/frontend/qml/ProtonUI/ButtonIconText.qml
+++ /dev/null
@@ -1,100 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// Button with full window width containing two icons (left and right) and text
-
-import QtQuick 2.8
-import QtQuick.Controls 2.1
-import ProtonUI 1.0
-
-AccessibleButton {
- id: root
- property alias leftIcon : leftIcon
- property alias rightIcon : rightIcon
- property alias main : mainText
-
- // dimensions
- width : viewContent.width
- height : Style.main.heightRow
- topPadding: 0
- bottomPadding: 0
- leftPadding: Style.main.leftMargin
- rightPadding: Style.main.rightMargin
-
- background : Rectangle{
- color: Qt.lighter(Style.main.background, root.hovered || root.activeFocus ? ( root.pressed ? 1.2: 1.1) :1.0)
- // line
- Rectangle {
- anchors.bottom : parent.bottom
- width : parent.width
- height : Style.main.heightLine
- color : Style.main.line
- }
- // pointing cursor
- MouseArea {
- anchors.fill : parent
- cursorShape : Qt.PointingHandCursor
- acceptedButtons: Qt.NoButton
- }
- }
-
- contentItem : Rectangle {
- color: "transparent"
- // Icon left
- Text {
- id: leftIcon
- anchors {
- verticalCenter : parent.verticalCenter
- left : parent.left
- }
- font {
- family : Style.fontawesome.name
- pointSize : Style.settings.iconSize * Style.pt
- }
- color : Style.main.textBlue
- text : Style.fa.hashtag
- }
-
- // Icon/Text right
- Text {
- id: rightIcon
- anchors {
- verticalCenter : parent.verticalCenter
- right : parent.right
- }
- font {
- family : Style.fontawesome.name
- pointSize : Style.settings.iconSize * Style.pt
- }
- color : Style.main.textBlue
- text : Style.fa.hashtag
- }
-
- // Label
- Text {
- id: mainText
- anchors {
- verticalCenter : parent.verticalCenter
- left : leftIcon.right
- leftMargin : leftIcon.text!="" ? Style.main.leftMargin : 0
- }
- font.pointSize : Style.settings.fontSize * Style.pt
- color : Style.main.text
- text : root.text
- }
- }
-}
diff --git a/internal/frontend/qml/ProtonUI/ButtonRounded.qml b/internal/frontend/qml/ProtonUI/ButtonRounded.qml
deleted file mode 100644
index 8fc58aa6..00000000
--- a/internal/frontend/qml/ProtonUI/ButtonRounded.qml
+++ /dev/null
@@ -1,92 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// Classic button with icon and text
-
-import QtQuick 2.8
-import QtQuick.Controls 2.1
-import QtGraphicalEffects 1.0
-import ProtonUI 1.0
-
-AccessibleButton {
- id: root
- property string fa_icon : ""
- property color color_main : Style.dialog.text
- property color color_minor : "transparent"
- property bool isOpaque : false
-
- text : "undef"
- state : root.hovered || root.activeFocus ? "hover" : "normal"
- width : Style.dialog.widthButton
- height : Style.dialog.heightButton
- scale : root.pressed ? 0.96 : 1.00
-
- background: Rectangle {
- border {
- color : root.color_main
- width : root.isOpaque ? 0 : Style.dialog.borderButton
- }
- radius : Style.dialog.radiusButton
- color : root.isOpaque ? root.color_minor : "transparent"
-
- MouseArea {
- anchors.fill : parent
- cursorShape : Qt.PointingHandCursor
- acceptedButtons: Qt.NoButton
- }
- }
-
- contentItem: Rectangle {
- color: "transparent"
-
- Row {
- id: mainText
- anchors.centerIn: parent
- spacing: 0
-
- Text {
- font {
- pointSize : Style.dialog.fontSize * Style.pt
- family : Style.fontawesome.name
- }
- color : color_main
- text : root.fa_icon=="" ? "" : root.fa_icon + " "
- }
-
- Text {
- font {
- pointSize : Style.dialog.fontSize * Style.pt
- }
- color : color_main
- text : root.text
- }
- }
-
- Glow {
- id: mainTextEffect
- anchors.fill : mainText
- source: mainText
- color: color_main
- opacity: 0.33
- }
- }
-
- states :[
- State {name: "normal"; PropertyChanges{ target: mainTextEffect; radius: 0 ; visible: false } },
- State {name: "hover" ; PropertyChanges{ target: mainTextEffect; radius: 3*Style.px ; visible: true } }
- ]
-}
diff --git a/internal/frontend/qml/ProtonUI/CheckBoxLabel.qml b/internal/frontend/qml/ProtonUI/CheckBoxLabel.qml
deleted file mode 100644
index 981103d6..00000000
--- a/internal/frontend/qml/ProtonUI/CheckBoxLabel.qml
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// input for date range
-
-import QtQuick 2.8
-import QtQuick.Controls 2.2
-import ProtonUI 1.0
-
-CheckBox {
- id: root
- spacing: Style.dialog.spacing
- padding: 0
- property color textColor : Style.main.text
- property color checkedColor : Style.main.textBlue
- property color uncheckedColor : Style.main.textInactive
- property string checkedSymbol : Style.fa.check_square_o
- property string uncheckedSymbol : Style.fa.square_o
- property alias symbolPointSize : symbol.font.pointSize
- background: Rectangle {
- color: Style.transparent
- }
- indicator: Text {
- id: symbol
- text : root.checked ? root.checkedSymbol : root.uncheckedSymbol
- color : root.checked ? root.checkedColor : root.uncheckedColor
- font {
- pointSize : Style.dialog.iconSize * Style.pt
- family : Style.fontawesome.name
- }
- }
- contentItem: Text {
- id: label
- text : root.text
- color : root.textColor
- font {
- pointSize: Style.dialog.fontSize * Style.pt
- }
- horizontalAlignment: Text.AlignHCenter
- verticalAlignment: Text.AlignVCenter
- leftPadding: Style.dialog.iconSize + root.spacing
- }
-}
diff --git a/internal/frontend/qml/ProtonUI/ClickIconText.qml b/internal/frontend/qml/ProtonUI/ClickIconText.qml
deleted file mode 100644
index 2da742ca..00000000
--- a/internal/frontend/qml/ProtonUI/ClickIconText.qml
+++ /dev/null
@@ -1,98 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// No border button with icon
-
-import QtQuick 2.8
-import QtQuick.Controls 2.1
-import ProtonUI 1.0
-
-AccessibleButton {
- id: root
-
- property string iconText : Style.fa.hashtag
- property color textColor : Style.main.text
- property int fontSize : Style.main.fontSize
- property int iconSize : Style.main.iconSize
- property int margin : iconText!="" ? Style.main.leftMarginButton : 0.0
- property bool iconOnRight : false
- property bool textBold : false
- property bool textUnderline : false
-
-
- TextMetrics {
- id: metrics
- text: root.text
- font: showText.font
- }
-
- TextMetrics {
- id: metricsIcon
- text : root.iconText
- font : showIcon.font
- }
-
- scale : root.pressed ? 0.96 : root.activeFocus ? 1.05 : 1.0
- height : Math.max(metrics.height, metricsIcon.height)
- width : metricsIcon.width*1.5 + margin + metrics.width + 4.0
- padding : 0.0
-
- background : Rectangle {
- color: Style.transparent
- MouseArea {
- anchors.fill : parent
- cursorShape : Qt.PointingHandCursor
- acceptedButtons: Qt.NoButton
- }
- }
-
- contentItem : Rectangle {
- color: Style.transparent
- Text {
- id: showIcon
- anchors {
- left : iconOnRight ? showText.right : parent.left
- leftMargin : iconOnRight ? margin : 0
- verticalCenter : parent.verticalCenter
- }
- font {
- pointSize : iconSize * Style.pt
- family : Style.fontawesome.name
- }
- color : textColor
- text : root.iconText
- }
-
- Text {
- id: showText
- anchors {
- verticalCenter : parent.verticalCenter
- left : iconOnRight ? parent.left : showIcon.right
- leftMargin : iconOnRight ? 0 : margin
- }
- color : textColor
- font {
- pointSize : root.fontSize * Style.pt
- bold: root.textBold
- underline: root.textUnderline
- }
- text : root.text
- }
- }
-}
-
-
diff --git a/internal/frontend/qml/ProtonUI/Dialog.qml b/internal/frontend/qml/ProtonUI/Dialog.qml
deleted file mode 100644
index eaaefcfb..00000000
--- a/internal/frontend/qml/ProtonUI/Dialog.qml
+++ /dev/null
@@ -1,164 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// Dialog with adding new user
-
-import QtQuick 2.8
-import QtQuick.Controls 2.1
-import QtQuick.Layouts 1.3
-import ProtonUI 1.0
-
-
-StackLayout {
- id: root
- property string title : "title"
- property string subtitle : ""
- property alias timer : timer
- property alias warning : warningText
- property bool isDialogBusy : false
- property real titleHeight : 2*titleText.anchors.topMargin + titleText.height + (warningText.visible ? warningText.anchors.topMargin + warningText.height : 0)
- property Item background : Rectangle {
- parent: root
- width: root.width
- height: root.height
- color : Style.dialog.background
- visible: root.visible
- z: -1
-
- // Looks like StackLayout explicatly sets visible=false to all viasual children except selected.
- // We want this background to be also visible.
- onVisibleChanged: {
- if (visible != parent.visible) {
- visible = parent.visible
- }
- }
-
- AccessibleText {
- id: titleText
- anchors {
- top: parent.top
- horizontalCenter: parent.horizontalCenter
- topMargin: Style.dialog.titleSize
- }
- font.pointSize : Style.dialog.titleSize * Style.pt
- color : Style.dialog.text
- text : root.title
- }
-
- AccessibleText {
- id: subtitleText
- anchors {
- top: titleText.bottom
- horizontalCenter: parent.horizontalCenter
- }
- font.pointSize : Style.dialog.fontSize * Style.pt
- color : Style.dialog.text
- text : root.subtitle
- visible : root.subtitle != ""
- }
-
- AccessibleText {
- id:warningText
- anchors {
- top: subtitleText.bottom
- horizontalCenter: parent.horizontalCenter
- }
- font {
- bold: true
- pointSize: Style.dialog.fontSize * Style.pt
- }
- text : ""
- color: Style.main.textBlue
- visible: false
- width: root.width
- horizontalAlignment: Text.AlignHCenter
- wrapMode: Text.WordWrap
- }
-
- // prevent any action below
- MouseArea {
- anchors.fill: parent
- hoverEnabled: true
- }
-
- ClickIconText {
- anchors {
- top: parent.top
- right: parent.right
- topMargin: Style.dialog.titleSize
- rightMargin: Style.dialog.titleSize
- }
- visible : !isDialogBusy
- iconText : Style.fa.times
- text : ""
- onClicked : root.hide()
- Accessible.description : qsTr("Close dialog %1", "Click to exit modal.").arg(root.title)
- }
- }
-
- Accessible.role: Accessible.Grouping
- Accessible.name: title
- Accessible.description: title
- Accessible.focusable: true
-
- onVisibleChanged: {
- if (background.visible != visible) {
- background.visible = visible
- }
- }
-
- visible : false
- anchors {
- left : parent.left
- right : parent.right
- top : titleBar.bottom
- bottom : parent.bottom
- }
- currentIndex : 0
-
-
- signal show()
- signal hide()
-
- function incrementCurrentIndex() {
- root.currentIndex++
- }
-
- function decrementCurrentIndex() {
- root.currentIndex--
- }
-
- onShow: {
- root.visible = true
- root.forceActiveFocus()
- }
-
- onHide: {
- root.timer.stop()
- root.currentIndex=0
- root.visible = false
- root.timer.stop()
- gui.winMain.tabbar.focusButton()
- }
-
- // QTimer is recommeded solution for creating trheads : http://doc.qt.io/qt-5/qtquick-threading-example.html
- Timer {
- id: timer
- interval: 300 // wait for transistion
- repeat: false
- }
-}
diff --git a/internal/frontend/qml/ProtonUI/DialogAddUser.qml b/internal/frontend/qml/ProtonUI/DialogAddUser.qml
deleted file mode 100644
index ba619540..00000000
--- a/internal/frontend/qml/ProtonUI/DialogAddUser.qml
+++ /dev/null
@@ -1,465 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// Dialog with adding new user
-
-import QtQuick 2.8
-import ProtonUI 1.0
-
-
-Dialog {
- id: root
-
- title : ""
-
- signal createAccount()
-
- property alias inputPassword : inputPassword
- property alias input2FAuth : input2FAuth
- property alias inputPasswMailbox : inputPasswMailbox
- //
- property alias username : inputUsername.text
- property alias usernameElided : usernameMetrics.elidedText
-
- isDialogBusy : currentIndex==waitingAuthIndex || currentIndex==addingAccIndex
-
- property bool isFirstAccount: false
-
- property color buttonOpaqueMain : "white"
-
-
- property int origin: 0
- property int nameAndPasswordIndex : 0
- property int waitingAuthIndex : 2
- property int twoFAIndex : 1
- property int mailboxIndex : 3
- property int addingAccIndex : 4
- property int newAccountIndex : 5
-
-
- signal cancel()
- signal okay()
-
- TextMetrics {
- id: usernameMetrics
- font: dialogWaitingAuthText.font
- elideWidth : Style.dialog.widthInput
- elide : Qt.ElideMiddle
- text : root.username
- }
-
- Column { // 0
- id: dialogNameAndPassword
- property int heightInputs : inputUsername.height + buttonRow.height + middleSep.height + inputPassword.height + middleSepPassw.height
-
- Rectangle {
- id: topSep
- color : "transparent"
- width : Style.main.dummy
- // Hacky hack: +10 is to make title of Dialog bigger so longer error can fit just fine.
- height : root.height/2 + 10 - (dialogNameAndPassword.heightInputs)/2
- }
-
- InputField {
- id: inputUsername
- iconText : Style.fa.user_circle
- label : qsTr("Username", "enter username to add account")
- onAccepted : inputPassword.focusInput = true
- }
-
- Rectangle { id: middleSepPassw; color : "transparent"; width : Style.main.dummy; height : Style.dialog.heightSeparator}
-
- InputField {
- id: inputPassword
- label : qsTr("Password", "password entry field")
- iconText : Style.fa.lock
- isPassword : true
- onAccepted : root.okay()
- }
-
- Rectangle { id: middleSep; color : "transparent"; width : Style.main.dummy; height : 2*Style.dialog.heightSeparator }
-
- Row {
- id: buttonRow
- anchors.horizontalCenter: parent.horizontalCenter
- spacing: Style.dialog.fontSize
- ButtonRounded {
- id:buttonCancel
- fa_icon : Style.fa.times
- text : qsTr("Cancel", "dismisses current action")
- color_main : Style.dialog.text
- onClicked : root.cancel()
- }
- ButtonRounded {
- id: buttonNext
- fa_icon : Style.fa.check
- text : qsTr("Next", "navigate to next page in add account flow")
- color_main : buttonOpaqueMain
- color_minor : Style.dialog.textBlue
- isOpaque : true
- onClicked : root.okay()
- }
- }
-
- Rectangle {
- color : "transparent"
- width : Style.main.dummy
- height : root.height - (topSep.height + dialogNameAndPassword.heightInputs + Style.main.bottomMargin + signUpForAccount.height)
- }
-
- ClickIconText {
- id: signUpForAccount
- anchors.horizontalCenter: parent.horizontalCenter
- fontSize : Style.dialog.fontSize
- iconSize : Style.dialog.fontSize
- iconText : "+"
- text : qsTr ("Sign Up for an Account", "takes user to web page where they can create a ProtonMail account")
- textBold : true
- textUnderline : true
- textColor : Style.dialog.text
- onClicked : root.createAccount()
- }
- }
-
- Column { // 1
- id: dialog2FA
- property int heightInputs : buttonRowPassw.height + middleSep2FA.height + input2FAuth.height
-
- Rectangle {
- color : "transparent"
- width : Style.main.dummy
- height : (root.height - dialog2FA.heightInputs)/2
- }
-
- InputField {
- id: input2FAuth
- label : qsTr("Two Factor Code", "two factor code entry field")
- iconText : Style.fa.lock
- onAccepted : root.okay()
- }
-
- Rectangle { id: middleSep2FA; color : "transparent"; width : Style.main.dummy; height : 2*Style.dialog.heightSeparator }
-
- Row {
- id: buttonRowPassw
- anchors.horizontalCenter: parent.horizontalCenter
- spacing: Style.dialog.fontSize
- ButtonRounded {
- id: buttonBack
- fa_icon: Style.fa.times
- text: qsTr("Back", "navigate back in add account flow")
- color_main: Style.dialog.text
- onClicked : root.cancel()
- }
- ButtonRounded {
- id: buttonNextTwo
- fa_icon: Style.fa.check
- text: qsTr("Next", "navigate to next page in add account flow")
- color_main: buttonOpaqueMain
- color_minor: Style.dialog.textBlue
- isOpaque: true
- onClicked : root.okay()
- }
- }
- }
-
- Column { // 2
- id: dialogWaitingAuth
- Rectangle { color : "transparent"; width : Style.main.dummy; height : (root.height-dialogWaitingAuthText.height) /2 }
- Text {
- id: dialogWaitingAuthText
- anchors.horizontalCenter: parent.horizontalCenter
- color: Style.dialog.text
- font.pointSize: Style.dialog.fontSize * Style.pt
- text : qsTr("Logging in") +"\n" + root.usernameElided
- horizontalAlignment: Text.AlignHCenter
- }
- }
-
- Column { // 3
- id: dialogMailboxPassword
- property int heightInputs : buttonRowMailbox.height + inputPasswMailbox.height + middleSepMailbox.height
-
- Rectangle { color : "transparent"; width : Style.main.dummy; height : (root.height - dialogMailboxPassword.heightInputs)/2}
-
- InputField {
- id: inputPasswMailbox
- label : qsTr("Mailbox password for %1", "mailbox password entry field").arg(root.usernameElided)
- iconText : Style.fa.lock
- isPassword : true
- onAccepted : root.okay()
- }
-
- Rectangle { id: middleSepMailbox; color : "transparent"; width : Style.main.dummy; height : 2*Style.dialog.heightSeparator }
-
- Row {
- id: buttonRowMailbox
- anchors.horizontalCenter: parent.horizontalCenter
- spacing: Style.dialog.fontSize
- ButtonRounded {
- id: buttonBackBack
- fa_icon: Style.fa.times
- text: qsTr("Back", "navigate back in add account flow")
- color_main: Style.dialog.text
- onClicked : root.cancel()
- }
- ButtonRounded {
- id: buttonLogin
- fa_icon: Style.fa.check
- text: qsTr("Next", "navigate to next page in add account flow")
- color_main: buttonOpaqueMain
- color_minor: Style.dialog.textBlue
- isOpaque: true
- onClicked : root.okay()
- }
- }
- }
-
- Column { // 4
- id: dialogWaitingAccount
-
- Rectangle { color : "transparent"; width : Style.main.dummy; height : (root.height - dialogWaitingAccountText.height )/2 }
-
- Text {
- id: dialogWaitingAccountText
- anchors.horizontalCenter: parent.horizontalCenter
- color: Style.dialog.text
- font {
- bold : true
- pointSize: Style.dialog.fontSize * Style.pt
- }
- text : qsTr("Adding account, please wait ...", "displayed after user has logged in, before new account is displayed")
- wrapMode: Text.Wrap
- }
- }
-
- Column { // 5
- id: dialogFirstUserAdded
-
- Rectangle { color : "transparent"; width : Style.main.dummy; height : (root.height - dialogWaitingAccountText.height - okButton.height*2 )/2 }
-
- Text {
- id: textFirstUser
- anchors.horizontalCenter: parent.horizontalCenter
- color: Style.dialog.text
- font {
- bold : false
- pointSize: Style.dialog.fontSize * Style.pt
- }
- width: 2*root.width/3
- horizontalAlignment: Text.AlignHCenter
- textFormat: Text.RichText
- text: ""+
- qsTr("Now you need to configure your client(s) to use the Bridge. Instructions for configuring your client can be found at", "") +
- "
https://protonmail.com/bridge/clients."
- wrapMode: Text.Wrap
- onLinkActivated: {
- Qt.openUrlExternally(link)
- }
- MouseArea {
- anchors.fill: parent
- cursorShape: parent.hoveredLink=="" ? Qt.PointingHandCursor : Qt.WaitCursor
- acceptedButtons: Qt.NoButton
- }
- }
-
- Rectangle { color : "transparent"; width : Style.main.dummy; height : okButton.height}
-
- ButtonRounded{
- id: okButton
- anchors.horizontalCenter: parent.horizontalCenter
- color_main: buttonOpaqueMain
- color_minor: Style.main.textBlue
- isOpaque: true
- text: qsTr("Okay", "confirms and dismisses a notification")
- onClicked: root.hide()
- }
- }
-
- function clear_user() {
- inputUsername.text = ""
- inputUsername.rightIcon = ""
- }
-
- function clear_passwd() {
- inputPassword.text = ""
- inputPassword.rightIcon = ""
- inputPassword.hidePasswordText()
- }
-
-
- function clear_2fa() {
- input2FAuth.text = ""
- input2FAuth.rightIcon = ""
- }
-
- function clear_passwd_mailbox() {
- inputPasswMailbox.text = ""
- inputPasswMailbox.rightIcon = ""
- inputPasswMailbox.hidePasswordText()
- }
-
- onCancel : {
- root.warning.visible=false
- if (currentIndex==0) {
- root.hide()
- } else {
- clear_passwd()
- clear_passwd_mailbox()
- currentIndex=0
- }
- }
-
-
- function check_inputs() {
- var isOK = true
- switch (currentIndex) {
- case nameAndPasswordIndex :
- isOK &= inputUsername.checkNonEmpty()
- isOK &= inputPassword.checkNonEmpty()
- break
- case twoFAIndex :
- isOK &= input2FAuth.checkNonEmpty()
- break
- case mailboxIndex :
- isOK &= inputPasswMailbox.checkNonEmpty()
- break
- }
- if (isOK) {
- warning.visible = false
- warning.text= ""
- } else {
- setWarning(qsTr("Field required", "a field that must be filled in to submit form"),0)
- }
- return isOK
- }
-
- function setWarning(msg, changeIndex) {
- // show message
- root.warning.text = msg
- root.warning.visible = true
- }
-
-
- onOkay : {
- var isOK = check_inputs()
- if (isOK) {
- root.origin = root.currentIndex
- switch (root.currentIndex) {
- case nameAndPasswordIndex:
- case twoFAIndex:
- root.currentIndex = waitingAuthIndex
- break;
- case mailboxIndex:
- root.currentIndex = addingAccIndex
- }
- timer.start()
- }
- }
-
- onShow: {
- root.title = qsTr ("Log in to your ProtonMail account", "displayed on screen when user enters username to begin adding account")
- root.warning.visible = false
- inputUsername.forceFocus()
- root.isFirstAccount = go.isFirstStart && accountsModel.count==0
- }
-
- function startAgain() {
- clear_passwd()
- clear_2fa()
- clear_passwd_mailbox()
- root.currentIndex = nameAndPasswordIndex
- root.inputPassword.focusInput = true
- }
-
- function finishLogin(){
- root.currentIndex = addingAccIndex
- var auth = go.addAccount(inputPasswMailbox.text)
- if (auth<0) {
- startAgain()
- return
- }
- }
-
- Connections {
- target: timer
-
- onTriggered : {
- timer.repeat = false
- switch (root.origin) {
- case nameAndPasswordIndex:
- var auth = go.login(inputUsername.text, inputPassword.text)
- if (auth < 0) {
- startAgain()
- break
- }
- if (auth == 1) {
- root.currentIndex = twoFAIndex
- root.input2FAuth.focusInput = true
- break
- }
- if (auth == 2) {
- root.currentIndex = mailboxIndex
- root.inputPasswMailbox.focusInput = true
- break
- }
- root.inputPasswMailbox.text = inputPassword.text
- root.finishLogin()
- break;
- case twoFAIndex:
- var auth = go.auth2FA(input2FAuth.text)
- if (auth < 0) {
- startAgain()
- break
- }
- if (auth == 1) {
- root.currentIndex = mailboxIndex
- root.inputPasswMailbox.focusInput = true
- break
- }
- root.inputPasswMailbox.text = inputPassword.text
- root.finishLogin()
- break;
- case mailboxIndex:
- root.finishLogin()
- break;
- }
- }
- }
-
- onHide: {
- // because hide slot is conneceted to processFinished it will update
- // the list evertyime `go` obejcet is finished
- clear_passwd()
- clear_passwd_mailbox()
- clear_2fa()
- clear_user()
- go.loadAccounts()
- if (root.isFirstAccount && accountsModel.count==1) {
- root.isFirstAccount=false
- root.currentIndex=5
- root.show()
- root.title=qsTr("Success, Account Added!", "shown after successful account addition")
- }
- }
-
- Keys.onPressed: {
- if (event.key == Qt.Key_Enter) {
- root.okay()
- }
- }
-}
diff --git a/internal/frontend/qml/ProtonUI/DialogConnectionTroubleshoot.qml b/internal/frontend/qml/ProtonUI/DialogConnectionTroubleshoot.qml
deleted file mode 100644
index bba28497..00000000
--- a/internal/frontend/qml/ProtonUI/DialogConnectionTroubleshoot.qml
+++ /dev/null
@@ -1,148 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// Dialog with Yes/No buttons
-
-import QtQuick 2.8
-import ProtonUI 1.0
-
-Dialog {
- id: root
-
- title : qsTr(
- "Common connection problems and solutions",
- "Title of the network troubleshooting modal"
- )
- isDialogBusy: false // can close
- property var parContent : [
- [
- qsTr("Allow alternative routing" , "Paragraph title"),
- qsTr(
- "In case Proton sites are blocked, this setting allows Bridge "+
- "to try alternative network routing to reach Proton, which can "+
- "be useful for bypassing firewalls or network issues. We recommend "+
- "keeping this setting on for greater reliability. "+
- 'Learn more'+
- " and "+
- 'enable here'+
- ".",
- "Paragraph content"
- ),
- ],
-
- [
- qsTr("No internet connection" , "Paragraph title"),
- qsTr(
- "Please make sure that your internet connection is working.",
- "Paragraph content"
- ),
- ],
-
- [
- qsTr("Internet Service Provider (ISP) problem" , "Paragraph title"),
- qsTr(
- "Try connecting to Proton from a different network (or use "+
- 'ProtonVPN'+
- " or "+
- 'Tor'+
- ").",
- "Paragraph content"
- ),
- ],
-
- [
- qsTr("Government block" , "Paragraph title"),
- qsTr(
- "Your country may be blocking access to Proton. Try using "+
- 'ProtonVPN'+
- " (or any other VPN) or "+
- 'Tor'+
- ".",
- "Paragraph content"
- ),
- ],
-
- [
- qsTr("Antivirus interference" , "Paragraph title"),
- qsTr(
- "Temporarily disable or remove your antivirus software.",
- "Paragraph content"
- ),
- ],
-
- [
- qsTr("Proxy/Firewall interference" , "Paragraph title"),
- qsTr(
- "Disable any proxies or firewalls, or contact your network administrator.",
- "Paragraph content"
- ),
- ],
-
- [
- qsTr("Still can’t find a solution" , "Paragraph title"),
- qsTr(
- "Contact us directly through our "+
- 'support form'+
- ", email (support@protonmail.com), or "+
- 'Twitter'+
- ".",
- "Paragraph content"
- ),
- ],
-
- [
- qsTr("Proton is down" , "Paragraph title"),
- qsTr(
- "Check "+
- 'Proton Status'+
- " for our system status.",
- "Paragraph content"
- ),
- ],
-
- ]
-
- Item {
- AccessibleText {
- anchors.centerIn: parent
- color: Style.old.pm_white
- linkColor: color
- width: parent.width - 50 * Style.px
- wrapMode: Text.WordWrap
- font.pointSize: Style.main.fontSize*Style.pt
- onLinkActivated: {
- if (link=="showProxy") {
- dialogGlobal.state= "toggleAllowProxy"
- dialogGlobal.show()
- } else {
- Qt.openUrlExternally(link)
- }
- }
- text: {
- var content=""
- for (var i=0; i"
- content += ""+par[0]+": "
- content += par[1]
- content += "\n"
- }
- return content
- }
- }
- }
-}
diff --git a/internal/frontend/qml/ProtonUI/DialogUpdate.qml b/internal/frontend/qml/ProtonUI/DialogUpdate.qml
deleted file mode 100644
index 0a6edb1e..00000000
--- a/internal/frontend/qml/ProtonUI/DialogUpdate.qml
+++ /dev/null
@@ -1,298 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// default options to make button accessible
-
-import QtQuick 2.8
-import QtQuick.Controls 2.2
-import ProtonUI 1.0
-
-
-Dialog {
- id: root
-
- property bool hasError : false
- property bool forceUpdate : false
-
- signal cancel()
- signal okay()
-
- title: forceUpdate ?
- qsTr("Update %1 now", "title of force update dialog").arg(go.programTitle):
- qsTr("Update to %1 %2", "title of normal update dialog").arg(go.programTitle).arg(go.updateVersion)
-
- isDialogBusy: currentIndex==1 || forceUpdate
-
- Rectangle { // 0: Release notes and confirm
- width: parent.width
- height: parent.height
- color: Style.transparent
-
- Column {
- anchors.centerIn: parent
- spacing: 5*Style.dialog.spacing
-
- AccessibleText {
- id:introduction
- anchors.horizontalCenter: parent.horizontalCenter
- color: Style.dialog.text
- linkColor: Style.dialog.textBlue
- font {
- pointSize: Style.dialog.fontSize * Style.pt
- }
- width: 2*root.width/3
- horizontalAlignment: Text.AlignHCenter
- wrapMode: Text.Wrap
-
- text: {
- if (forceUpdate) {
- if (go.updateCanInstall) {
- return qsTr('You need to update this app to continue using it.
- Update now or manually download the most recent version here:
- %1
- Learn why you need to update',
- "Message for force-update").arg(go.updateLandingPage)
- } else {
- return qsTr('You need to update this app to continue using it.
- Download the most recent version here:
- %1
- Learn why you need to update',
- "Message for force-update").arg(go.updateLandingPage)
- }
- }
-
- if (go.updateCanInstall) {
- return qsTr('Update to the newest version or download it from:
- %1
- View release notes',
- "Message for manual update").arg(go.updateLandingPage).arg(go.updateReleaseNotesLink)
- } else {
- return qsTr('Update to the newest version from:
- %1
- View release notes',
- "Message for manual update").arg(go.updateLandingPage).arg(go.updateReleaseNotesLink)
- }
- }
-
-
- onLinkActivated : {
- console.log("clicked link:", link)
- Qt.openUrlExternally(link)
- }
-
- MouseArea {
- anchors.fill: parent
- cursorShape: introduction.hoveredLink ? Qt.PointingHandCursor : Qt.ArrowCursor
- acceptedButtons: Qt.NoButton
- }
- }
-
- CheckBoxLabel {
- id: autoUpdate
- anchors.horizontalCenter: parent.horizontalCenter
- text: qsTr("Automatically update in the future", "Checkbox label for using autoupdates later on")
- checked: go.isAutoUpdate
- onToggled: go.toggleAutoUpdate()
- visible: !root.forceUpdate && (go.isAutoUpdate != undefined)
- }
-
- Row {
- anchors.horizontalCenter: parent.horizontalCenter
- spacing: Style.dialog.spacing
-
- ButtonRounded {
- fa_icon: Style.fa.times
- text: root.forceUpdate ? qsTr("Quit") : qsTr("Cancel")
- color_main: Style.dialog.text
- onClicked: root.forceUpdate ? Qt.quit() : root.cancel()
- }
-
- ButtonRounded {
- fa_icon: Style.fa.check
- text: qsTr("Update")
- visible: go.updateCanInstall
- color_main: Style.dialog.text
- color_minor: Style.main.textBlue
- isOpaque: true
- onClicked: root.okay()
- }
- }
- }
- }
-
- Rectangle { // 1: Installing update
- id: updateStatus
- width: parent.width
- height: parent.height
- color: Style.transparent
-
- Column {
- anchors.centerIn: parent
- spacing: Style.dialog.spacing
-
- AccessibleText {
- color: Style.dialog.text
- font {
- pointSize: Style.dialog.fontSize * Style.pt
- bold: false
- }
- width: 2*root.width/3
- horizontalAlignment: Text.AlignHCenter
- wrapMode: Text.Wrap
- text: qsTr("Updating...")
- }
-
- ProgressBar {
- id: updateProgressBar
- width: 2*updateStatus.width/3
- height: Style.exporting.rowHeight
- //implicitWidth : 2*updateStatus.width/3
- //implicitHeight : Style.exporting.rowHeight
- indeterminate: true
- //value: 0.5
- //property int current: go.total * go.progress
- //property bool isFinished: finishedPartBar.width == progressbar.width
- background: Rectangle {
- radius : Style.exporting.boxRadius
- color : Style.exporting.progressBackground
- }
-
- contentItem: Item {
- clip: true
- Rectangle {
- id: progressIndicator
- width : updateProgressBar.indeterminate ? 50 : parent.width * updateProgressBar.visualPosition
- height : parent.height
- radius : Style.exporting.boxRadius
- gradient : Gradient {
- GradientStop { position: 0.00; color: Qt.lighter(Style.main.textBlue,1.1) }
- GradientStop { position: 0.66; color: Style.main.textBlue }
- GradientStop { position: 1.00; color: Qt.darker(Style.main.textBlue,1.1) }
- }
-
- Behavior on width {
- NumberAnimation { duration:300; easing.type: Easing.InOutQuad }
- }
-
- SequentialAnimation {
- running: updateProgressBar.visible && updateProgressBar.indeterminate
- loops: Animation.Infinite
-
- SmoothedAnimation {
- target: progressIndicator
- property: "x"
- from: 0
- to: updateProgressBar.width - progressIndicator.width
- duration: 2000
- }
-
- SmoothedAnimation {
- target: progressIndicator
- property: "x"
- from: updateProgressBar.width - progressIndicator.width
- to: 0
- duration: 2000
- }
- }
- }
- Text {
- anchors.centerIn: parent
- text: ""
- color: Style.main.background
- font {
- pointSize: Style.dialog.fontSize * Style.pt
- }
- }
- }
- }
- }
- }
-
- Rectangle { // 2: Something went wrong / All ok, closing bridge
- width: parent.width
- height: parent.height
- color: Style.transparent
-
- Column {
- anchors.centerIn: parent
- spacing: 5*Style.dialog.spacing
-
- AccessibleText {
- color: Style.dialog.text
- linkColor: Style.dialog.textBlue
- font {
- pointSize: Style.dialog.fontSize * Style.pt
- }
- width: 2*root.width/3
- horizontalAlignment: Text.AlignHCenter
- wrapMode: Text.Wrap
- text: !root.hasError ? qsTr('%1 will restart now to finish the update.', "message after successful update").arg(go.programTitle) :
- qsTr('The update procedure was not successful!
Please follow the download link and update manually.
%1').arg(go.updateLandingPage)
-
- onLinkActivated : {
- console.log("clicked link:", link)
- Qt.openUrlExternally(link)
- }
-
- MouseArea {
- anchors.fill: parent
- cursorShape: parent.hoveredLink ? Qt.PointingHandCursor : Qt.ArrowCursor
- acceptedButtons: Qt.NoButton
- }
- }
-
- ButtonRounded{
- anchors.horizontalCenter: parent.horizontalCenter
- visible: root.hasError
- text: qsTr("Close")
- onClicked: root.cancel()
- }
- }
- }
-
- function clear() {
- root.hasError = false
- go.progress = 0.0
- go.progressDescription = "0"
- }
-
- function finished(hasError) {
- root.hasError = hasError
- root.currentIndex = 2
- }
-
- onShow: {
- root.clear()
- }
-
- onHide: {
- root.clear()
- }
-
- onOkay: {
- switch (root.currentIndex) {
- case 0:
- go.startManualUpdate()
- root.currentIndex = 1
- break
- }
- }
-
- onCancel: {
- root.hide()
- }
-}
diff --git a/internal/frontend/qml/ProtonUI/FileAndFolderSelect.qml b/internal/frontend/qml/ProtonUI/FileAndFolderSelect.qml
deleted file mode 100644
index 9dc75905..00000000
--- a/internal/frontend/qml/ProtonUI/FileAndFolderSelect.qml
+++ /dev/null
@@ -1,78 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// one line input text field with label
-import QtQuick 2.8
-import QtQuick.Controls 2.2
-import QtQuick.Dialogs 1.0
-import ProtonUI 1.0
-
-Row {
- id: root
- spacing: Style.dialog.spacing
-
- property string title : "title"
-
- property alias path: inputPath.text
- property alias inputPath: inputPath
- property alias dialogVisible: pathDialog.visible
-
- InputBox {
- id: inputPath
- anchors {
- bottom: parent.bottom
- }
- spacing: Style.dialog.spacing
- field {
- height: browseButton.height
- width: root.width - root.spacing - browseButton.width
- }
-
- label: title
- Component.onCompleted: sanitizePath(pathDialog.shortcuts.home)
- }
-
- ButtonRounded {
- id: browseButton
- anchors {
- bottom: parent.bottom
- }
- height: Style.dialog.heightInput
- color_main: Style.main.textBlue
- fa_icon: Style.fa.folder_open
- text: qsTr("Browse", "click to look through directory for a file or folder")
- onClicked: pathDialog.visible = true
- }
-
- FileDialog {
- id: pathDialog
- title: root.title
- folder: shortcuts.home
- onAccepted: sanitizePath(pathDialog.fileUrl.toString())
- selectFolder: true
- }
-
- function sanitizePath(path) {
- var pattern = "file://"
- if (go.goos=="windows") pattern+="/"
- inputPath.text = path.replace(pattern, "")
- }
-
- function checkNonEmpty() {
- return inputPath.text != ""
- }
-}
diff --git a/internal/frontend/qml/ProtonUI/InfoToolTip.qml b/internal/frontend/qml/ProtonUI/InfoToolTip.qml
deleted file mode 100644
index 09cc6398..00000000
--- a/internal/frontend/qml/ProtonUI/InfoToolTip.qml
+++ /dev/null
@@ -1,101 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// on hover information
-
-import QtQuick 2.8
-import QtQuick.Controls 2.2
-import ProtonUI 1.0
-
-Text { // info icon
- id:root
- property alias info : tip.text
- font {
- family: Style.fontawesome.name
- pointSize : Style.dialog.iconSize * Style.pt
- }
- text: Style.fa.info_circle
- color: Style.main.textDisabled
-
- MouseArea {
- anchors.fill: parent
- hoverEnabled: true
-
- onEntered : tip.visible=true
- onExited : tip.visible=false
- }
-
- ToolTip {
- id: tip
- width: Style.bubble.width
- x: - 0.2*tip.width
- y: - tip.height
-
- topPadding : Style.main.fontSize/2
- bottomPadding : Style.main.fontSize/2
- leftPadding : Style.bubble.widthPane + Style.dialog.spacing
- rightPadding: Style.dialog.spacing
- delay: 800
-
- background : Rectangle {
- id: bck
- color: Style.bubble.paneBackground
- radius : Style.bubble.radius
-
-
- Text {
- id: icon
- color: Style.bubble.background
- text: Style.fa.info_circle
- font {
- family : Style.fontawesome.name
- pointSize : Style.dialog.iconSize * Style.pt
- }
- anchors {
- verticalCenter : bck.verticalCenter
- left : bck.left
- leftMargin : (Style.bubble.widthPane - icon.width) / 2
- }
- }
-
- Rectangle { // right edge
- anchors {
- fill : bck
- leftMargin : Style.bubble.widthPane
- }
- radius: parent.radius
- color: Style.bubble.background
- }
-
- Rectangle { // center background
- anchors {
- fill : parent
- leftMargin : Style.bubble.widthPane
- rightMargin : Style.bubble.widthPane
- }
- color: Style.bubble.background
- }
- }
-
- contentItem : Text {
- text: tip.text
- color: Style.bubble.text
- wrapMode: Text.Wrap
- font.pointSize: Style.main.fontSize * Style.pt
- }
- }
-}
diff --git a/internal/frontend/qml/ProtonUI/InformationBar.qml b/internal/frontend/qml/ProtonUI/InformationBar.qml
deleted file mode 100644
index ef2fa00a..00000000
--- a/internal/frontend/qml/ProtonUI/InformationBar.qml
+++ /dev/null
@@ -1,371 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// Important information under title bar
-
-import QtQuick 2.8
-import QtQuick.Window 2.2
-import QtQuick.Controls 2.1
-import ProtonUI 1.0
-
-Rectangle {
- id: root
- property var iTry: 0
- property var second: 1000 // convert millisecond to second
- property bool isVisible: true
- property var fontSize : 1.2 * Style.main.fontSize
- color : "black"
- state: "upToDate"
-
- Row {
- id: messageRow
- anchors.centerIn: root
- visible: root.isVisible
- spacing: Style.main.leftMarginButton
-
- AccessibleText {
- id: message
- font.pointSize: root.fontSize * Style.pt
- }
-
- ClickIconText {
- id: linkText
- anchors.verticalCenter : message.verticalCenter
- iconText : " "
- fontSize : root.fontSize
- textUnderline: true
- }
-
- ClickIconText {
- id: actionText
- anchors.verticalCenter : message.verticalCenter
- iconText : " "
- fontSize : root.fontSize
- textUnderline: true
- }
- Text {
- id: separatorText
- anchors.baseline : message.baseline
- color: Style.main.text
- font {
- pointSize : root.fontSize * Style.pt
- bold : true
- }
- }
- ClickIconText {
- id: action2Text
- anchors.verticalCenter : message.verticalCenter
- iconText : ""
- fontSize : root.fontSize
- textUnderline: true
- }
- }
-
- ClickIconText {
- id: closeSign
- anchors.verticalCenter : messageRow.verticalCenter
- anchors.right: root.right
- iconText : Style.fa.close
- fontSize : root.fontSize
- textUnderline: true
- }
-
- onStateChanged : {
- switch (root.state) {
- case "internetCheck":
- break;
- case "noInternet" :
- break;
- case "oldVersion":
- break;
- case "forceUpdate":
- break;
- case "upToDate":
- break;
- case "updateRestart":
- break;
- case "updateError":
- break;
- default :
- break;
- }
- }
-
- states: [
- State {
- name: "internetCheck"
- PropertyChanges {
- target: root
- height: 2* Style.main.fontSize
- isVisible: true
- color: Style.main.textOrange
- }
- PropertyChanges {
- target: message
- color: Style.main.background
- text: qsTr("Checking connection. Please wait...", "displayed after user retries internet connection")
- }
- PropertyChanges {
- target: linkText
- visible: false
- }
- PropertyChanges {
- target: actionText
- visible: false
- }
- PropertyChanges {
- target: separatorText
- visible: false
- }
- PropertyChanges {
- target: action2Text
- visible: false
- }
- PropertyChanges {
- target: closeSign
- visible: false
- }
- },
- State {
- name: "noInternet"
- PropertyChanges {
- target: root
- height: 2* Style.main.fontSize
- isVisible: true
- color: Style.main.textRed
- }
- PropertyChanges {
- target: message
- color: Style.main.line
- text: qsTr("Cannot contact server. Please wait...", "displayed when the app is disconnected from the internet or server has problems")
- }
- PropertyChanges {
- target: linkText
- visible: false
- }
- PropertyChanges {
- target: separatorText
- visible: false
- text: "|"
- }
- PropertyChanges {
- target: action2Text
- visible: true
- text: qsTr("Troubleshoot", "Show modal screen with additional tips for troubleshooting connection issues")
- onClicked: {
- dialogConnectionTroubleshoot.show()
- }
- }
- PropertyChanges {
- target: closeSign
- visible: false
- }
- },
- State {
- name: "oldVersion"
- PropertyChanges {
- target: root
- height: 2* Style.main.fontSize
- isVisible: true
- color: Style.main.textBlue
- }
- PropertyChanges {
- target: message
- color: Style.main.background
- text: qsTr("Update available", "displayed in a notification when an app update is available")
- }
- PropertyChanges {
- target: linkText
- visible: true
- text: qsTr("Release Notes", "display the release notes from the new version")
- onClicked: gui.openReleaseNotes()
- }
- PropertyChanges {
- target: actionText
- visible: true
- text: qsTr("Update", "click to update to a new version when one is available")
- onClicked: {
- winMain.dialogUpdate.show()
- }
- }
- PropertyChanges {
- target: separatorText
- visible: false
- }
- PropertyChanges {
- target: action2Text
- visible: false
- }
- PropertyChanges {
- target: closeSign
- visible: true
- onClicked: {
- go.updateState = "upToDate"
- }
- }
- },
- State {
- name: "forceUpdate"
- PropertyChanges {
- target: root
- height: 2* Style.main.fontSize
- isVisible: true
- color: Style.main.textRed
- }
- PropertyChanges {
- target: message
- color: Style.main.line
- text: qsTr("%1 is outdated.", "displayed in a notification when app is outdated").arg(go.programTitle)
- }
- PropertyChanges {
- target: linkText
- visible: false
- }
- PropertyChanges {
- target: actionText
- visible: true
- text: qsTr("Update", "click to update to a new version when one is available")
- onClicked: {
- winMain.dialogUpdate.show()
- }
- }
- PropertyChanges {
- target: separatorText
- visible: false
- }
- PropertyChanges {
- target: action2Text
- visible: false
- }
- PropertyChanges {
- target: closeSign
- visible: false
- }
- },
- State {
- name: "upToDate"
- PropertyChanges {
- target: root
- height: 0
- isVisible: false
- color: Style.main.textBlue
- }
- PropertyChanges {
- target: message
- color: Style.main.background
- text: ""
- }
- PropertyChanges {
- target: linkText
- visible: false
- }
- PropertyChanges {
- target: actionText
- visible: false
- }
- PropertyChanges {
- target: separatorText
- visible: false
- }
- PropertyChanges {
- target: action2Text
- visible: false
- }
- PropertyChanges {
- target: closeSign
- visible: false
- }
- },
- State {
- name: "updateRestart"
- PropertyChanges {
- target: root
- height: 2* Style.main.fontSize
- isVisible: true
- color: Style.main.textBlue
- }
- PropertyChanges {
- target: message
- color: Style.main.background
- text: qsTr("%1 update is ready", "displayed in a notification when an app update is installed and restart is needed").arg(go.programTitle)
- }
- PropertyChanges {
- target: linkText
- visible: false
- }
- PropertyChanges {
- target: actionText
- visible: true
- text: qsTr("Restart now", "click to restart application as new version was installed")
- onClicked: {
- go.setToRestart()
- Qt.quit()
- }
- }
- PropertyChanges {
- target: separatorText
- visible: false
- }
- PropertyChanges {
- target: action2Text
- visible: false
- }
- PropertyChanges {
- target: closeSign
- visible: false
- }
- },
- State {
- name: "updateError"
- PropertyChanges {
- target: root
- height: 2* Style.main.fontSize
- isVisible: true
- color: Style.main.textRed
- }
- PropertyChanges {
- target: message
- color: Style.main.line
- text: qsTr("Sorry, %1 couldn't update.", "displayed in a notification when app failed to autoupdate").arg(go.programTitle)
- }
- PropertyChanges {
- target: linkText
- visible: false
- }
- PropertyChanges {
- target: actionText
- visible: true
- text: qsTr("Please update manually", "click to open download page to update manally")
- onClicked: {
- Qt.openUrlExternally(go.updateLandingPage)
- }
- }
- PropertyChanges {
- target: separatorText
- visible: false
- }
- PropertyChanges {
- target: action2Text
- visible: false
- }
- PropertyChanges {
- target: closeSign
- visible: false
- }
- }
- ]
-}
diff --git a/internal/frontend/qml/ProtonUI/InputBox.qml b/internal/frontend/qml/ProtonUI/InputBox.qml
deleted file mode 100644
index 8b086859..00000000
--- a/internal/frontend/qml/ProtonUI/InputBox.qml
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// one line input text field with label
-import QtQuick 2.8
-import QtQuick.Controls 2.2
-import QtQuick.Controls.Styles 1.4
-import ProtonUI 1.0
-import QtGraphicalEffects 1.0
-
-Column {
- id: root
- property alias label: textlabel.text
- property alias placeholderText: inputField.placeholderText
- property alias echoMode: inputField.echoMode
- property alias text: inputField.text
- property alias field: inputField
-
- signal accepted()
-
- spacing: Style.dialog.heightSeparator
-
- Text {
- id: textlabel
- font {
- pointSize: Style.dialog.fontSize * Style.pt
- bold: true
- }
- color: Style.dialog.text
- }
-
-
- TextField {
- id: inputField
- width: Style.dialog.widthInput
- height: Style.dialog.heightButton
- selectByMouse : true
- selectionColor : Style.main.textBlue
- padding : Style.dialog.radiusButton
- color : Style.dialog.text
- font {
- pointSize : Style.dialog.fontSize * Style.pt
- }
- background: Rectangle {
- color : Style.dialog.background
- radius: Style.dialog.radiusButton
- border {
- color : Style.dialog.line
- width : Style.dialog.borderInput
- }
- layer.enabled: true
- layer.effect: FastBlur {
- anchors.fill: parent
- radius: 8 * Style.px
- }
- }
- }
-
- Connections {
- target : inputField
- onAccepted : root.accepted()
- }
-}
diff --git a/internal/frontend/qml/ProtonUI/InputField.qml b/internal/frontend/qml/ProtonUI/InputField.qml
deleted file mode 100644
index 32af1b13..00000000
--- a/internal/frontend/qml/ProtonUI/InputField.qml
+++ /dev/null
@@ -1,187 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// one line input text field with label
-
-import QtQuick 2.8
-import QtQuick.Controls 2.1
-import ProtonUI 1.0
-
-Column {
- id: root
- property alias focusInput : inputField.focus
- property alias label : textlabel.text
- property alias iconText : iconInput.text
- property alias placeholderText : inputField.placeholderText
- property alias text : inputField.text
- property bool isPassword : false
- property string rightIcon : ""
-
- signal accepted()
- signal editingFinished()
-
- spacing: Style.dialog.heightSeparator
- anchors.horizontalCenter : parent.horizontalCenter
-
- AccessibleText {
- id: textlabel
- anchors.left : parent.left
- font {
- pointSize : Style.dialog.fontSize * Style.pt
- bold : true
- }
- horizontalAlignment: Text.AlignHCenter
- color : Style.dialog.text
- }
-
- Rectangle {
- id: inputWrap
- anchors.horizontalCenter : parent.horizontalCenter
- width : Style.dialog.widthInput
- height : Style.dialog.heightInput
- color : "transparent"
-
- Text {
- id: iconInput
- anchors {
- top : parent.top
- left : parent.left
- }
- color : Style.dialog.text
- font {
- pointSize : Style.dialog.iconSize * Style.pt
- family : Style.fontawesome.name
- }
- text: "o"
- }
-
- TextField {
- id: inputField
- anchors {
- fill: inputWrap
- leftMargin : Style.dialog.iconSize+Style.dialog.fontSize
- bottomMargin : inputWrap.height - Style.dialog.iconSize
- }
- verticalAlignment : TextInput.AlignTop
- horizontalAlignment : TextInput.AlignLeft
- selectByMouse : true
- color : Style.dialog.text
- selectionColor : Style.main.textBlue
- font {
- pointSize : Style.dialog.fontSize * Style.pt
- }
- padding: 0
- background: Rectangle {
- anchors.fill: parent
- color : "transparent"
- }
- Component.onCompleted : {
- if (isPassword) {
- echoMode = TextInput.Password
- } else {
- echoMode = TextInput.Normal
- }
- }
-
- Accessible.name: textlabel.text
- Accessible.description: textlabel.text
- }
-
- Text {
- id: iconRight
- anchors {
- top : parent.top
- right : parent.right
- }
- color : Style.dialog.text
- font {
- pointSize : Style.dialog.iconSize * Style.pt
- family : Style.fontawesome.name
- }
- text: ( !isPassword ? "" : (
- inputField.echoMode == TextInput.Password ? Style.fa.eye : Style.fa.eye_slash
- )) + " " + rightIcon
- MouseArea {
- anchors.fill: parent
- onClicked: {
- if (isPassword) {
- if (inputField.echoMode == TextInput.Password) inputField.echoMode = TextInput.Normal
- else inputField.echoMode = TextInput.Password
- }
- }
- }
- }
-
- Rectangle {
- anchors {
- left : parent.left
- right : parent.right
- bottom : parent.bottom
- }
- height: Math.max(Style.main.border,1)
- color: Style.dialog.text
- }
- }
-
- function clear() {
- inputField.text = ""
- rightIcon = ""
- }
-
- function checkNonEmpty() {
- if (inputField.text == "") {
- rightIcon = Style.fa.exclamation_triangle
- root.placeholderText = ""
- inputField.focus = true
- return false
- } else {
- rightIcon = Style.fa.check_circle
- }
- return true
- }
-
- function hidePasswordText() {
- if (root.isPassword) inputField.echoMode = TextInput.Password
- }
-
- function checkIsANumber(){
- if (/^\d+$/.test(inputField.text)) {
- rightIcon = Style.fa.check_circle
- return true
- }
- rightIcon = Style.fa.exclamation_triangle
- root.placeholderText = ""
- inputField.focus = true
- return false
- }
-
- function forceFocus() {
- inputField.forceActiveFocus()
- }
-
- Connections {
- target: inputField
- onAccepted: root.accepted()
- onEditingFinished: root.editingFinished()
- }
-
- Keys.onPressed: {
- if (event.key == Qt.Key_Enter) {
- root.accepted()
- }
- }
-}
diff --git a/internal/frontend/qml/ProtonUI/InstanceExistsWindow.qml b/internal/frontend/qml/ProtonUI/InstanceExistsWindow.qml
deleted file mode 100644
index ed666876..00000000
--- a/internal/frontend/qml/ProtonUI/InstanceExistsWindow.qml
+++ /dev/null
@@ -1,79 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// This is main window
-
-import QtQuick 2.8
-import QtQuick.Window 2.2
-import ProtonUI 1.0
-
-
-// Main Window
-Window {
- id:winMain
-
- // main window appeareance
- width : Style.main.width
- height : Style.main.height
- flags : Qt.Window | Qt.Dialog
- title: qsTr("ProtonMail Bridge", "app title")
- color : Style.main.background
- visible : true
-
- Text {
- id: title
- anchors {
- horizontalCenter: parent.horizontalCenter
- top: parent.top
- topMargin: Style.main.topMargin
- }
- font{
- pointSize: Style.dialog.titleSize * Style.pt
- }
- color: Style.main.text
- text:
- "" + Style.fa.exclamation_triangle + " " +
- qsTr ("Warning: Instance exists", "displayed when a version of the app is opened while another is already running")
- }
-
- Text {
- id: message
- anchors.centerIn : parent
- horizontalAlignment: Text.AlignHCenter
- font.pointSize: Style.dialog.fontSize * Style.pt
- color: Style.main.text
- width: 2*parent.width/3
- wrapMode: Text.Wrap
- text: qsTr("An instance of the ProtonMail Bridge is already running.", "displayed when a version of the app is opened while another is already running") + " " +
- qsTr("Please close the existing ProtonMail Bridge process before starting a new one.", "displayed when a version of the app is opened while another is already running")+ " " +
- qsTr("This program will close now.", "displayed when a version of the app is opened while another is already running")
- }
-
- ButtonRounded {
- anchors {
- horizontalCenter: parent.horizontalCenter
- bottom: parent.bottom
- bottomMargin: Style.main.bottomMargin
- }
- text: qsTr("Okay", "confirms and dismisses a notification")
- color_main: Style.dialog.text
- color_minor: Style.main.textBlue
- isOpaque: true
- onClicked: Qt.quit()
- }
-}
-
diff --git a/internal/frontend/qml/ProtonUI/LogoHeader.qml b/internal/frontend/qml/ProtonUI/LogoHeader.qml
deleted file mode 100644
index e7e4ed41..00000000
--- a/internal/frontend/qml/ProtonUI/LogoHeader.qml
+++ /dev/null
@@ -1,150 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// Header of window with logo and buttons
-
-import QtQuick 2.8
-import ProtonUI 1.0
-import QtQuick.Window 2.2
-
-
-Rectangle {
- id: root
- // dimensions
- property Window parentWin
- property string title: "ProtonMail Bridge"
- property bool hasIcon : true
- anchors.top : parent.top
- anchors.right : parent.right
- width : Style.main.width
- height : Style.title.height
- // style
- color : Style.title.background
-
- signal hideClicked()
-
- // Drag to move : https://stackoverflow.com/a/18927884
- MouseArea {
- property variant clickPos: "1,1"
- anchors.fill: parent
- onPressed: {
- clickPos = Qt.point(mouse.x,mouse.y)
- }
- onPositionChanged: {
- var delta = Qt.point(mouse.x-clickPos.x, mouse.y-clickPos.y)
- parentWin.x += delta.x;
- parentWin.y += delta.y;
- }
- }
-
- // logo
- Image {
- id: imgLogo
- height : Style.title.imgHeight
- fillMode : Image.PreserveAspectFit
- visible: root.hasIcon
- anchors {
- left : root.left
- leftMargin : Style.title.leftMargin
- verticalCenter : root.verticalCenter
- }
- //source : "qrc://logo.svg"
- source : "logo.svg"
- smooth : true
- }
-
- TextMetrics {
- id: titleMetrics
- elideWidth: 2*root.width/3
- elide: Qt.ElideMiddle
- font: titleText.font
- text: root.title
- }
-
- // Title
- Text {
- id: titleText
- anchors {
- left : hasIcon ? imgLogo.right : parent.left
- leftMargin : hasIcon ? Style.title.leftMargin : Style.main.leftMargin
- verticalCenter : root.verticalCenter
- }
- text : titleMetrics.elidedText
- color : Style.title.text
- font.pointSize : Style.title.fontSize * Style.pt
- }
-
- // Underline Button
- Rectangle {
- id: buttonUndrLine
- anchors {
- verticalCenter : root.verticalCenter
- right : buttonCross.left
- rightMargin : 2*Style.title.fontSize
- }
- width : Style.title.fontSize
- height : Style.title.fontSize
- color : "transparent"
- Canvas {
- anchors.fill: parent
- onPaint: {
- var val = Style.title.fontSize
- var ctx = getContext("2d")
- ctx.strokeStyle = 'white'
- ctx.strokeWidth = 4
- ctx.moveTo(0 , val-1)
- ctx.lineTo(val, val-1)
- ctx.stroke()
- }
- }
- MouseArea {
- anchors.fill: parent
- onClicked: root.hideClicked()
- }
- }
-
- // Cross Button
- Rectangle {
- id: buttonCross
- anchors {
- verticalCenter : root.verticalCenter
- right : root.right
- rightMargin : Style.main.rightMargin
- }
- width : Style.title.fontSize
- height : Style.title.fontSize
- color : "transparent"
- Canvas {
- anchors.fill: parent
- onPaint: {
- var val = Style.title.fontSize
- var ctx = getContext("2d")
- ctx.strokeStyle = 'white'
- ctx.strokeWidth = 4
- ctx.moveTo(0,0)
- ctx.lineTo(val,val)
- ctx.moveTo(val,0)
- ctx.lineTo(0,val)
- ctx.stroke()
- }
- }
- MouseArea {
- anchors.fill: parent
- onClicked: root.hideClicked()
- }
- }
-}
diff --git a/internal/frontend/qml/ProtonUI/PopupMessage.qml b/internal/frontend/qml/ProtonUI/PopupMessage.qml
deleted file mode 100644
index 88d735ae..00000000
--- a/internal/frontend/qml/ProtonUI/PopupMessage.qml
+++ /dev/null
@@ -1,122 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// Popup message
-import QtQuick 2.8
-import QtQuick.Controls 2.2
-import ProtonUI 1.0
-
-Rectangle {
- id: root
- color: Style.transparent
- property alias text : message.text
- property alias checkbox : checkbox
- property alias buttonQuit : buttonQuit
- property alias buttonOkay : buttonOkay
- property alias buttonYes : buttonYes
- property alias buttonNo : buttonNo
- property alias buttonRetry : buttonRetry
- property alias buttonSkip : buttonSkip
- property alias buttonCancel : buttonCancel
- property alias msgWidth : backgroundInp.width
- property string msgID : ""
- visible: false
-
- signal clickedOkay()
- signal clickedYes()
- signal clickedNo()
- signal clickedRetry()
- signal clickedSkip()
- signal clickedCancel()
-
- MouseArea { // prevent action below
- anchors.fill: parent
- hoverEnabled: true
- }
-
- Rectangle {
- id: backgroundInp
- anchors.centerIn : root
- color : Style.errorDialog.background
- radius : Style.errorDialog.radius
- width : parent.width/3.
- height : contentInp.height
-
- Column {
- id: contentInp
- anchors.horizontalCenter: backgroundInp.horizontalCenter
- spacing: Style.dialog.heightSeparator
- topPadding: Style.dialog.heightSeparator
- bottomPadding: Style.dialog.heightSeparator
-
- AccessibleText {
- id: message
- font {
- pointSize : Style.errorDialog.fontSize * Style.pt
- bold : true
- }
- color: Style.errorDialog.text
- horizontalAlignment: Text.AlignHCenter
- width : backgroundInp.width - 2*Style.main.rightMargin
- wrapMode: Text.Wrap
- }
-
- CheckBoxLabel {
- id: checkbox
- text: ""
- checked: false
- visible: (text != "")
- textColor : Style.errorDialog.text
- checkedColor: Style.errorDialog.text
- uncheckedColor: Style.errorDialog.text
- anchors.horizontalCenter : parent.horizontalCenter
- }
-
- Row {
- spacing: Style.dialog.spacing
- anchors.horizontalCenter : parent.horizontalCenter
-
- ButtonRounded { id : buttonQuit ; text : qsTr ( "Stop & quit", "" ) ; onClicked : root.clickedYes ( ) ; visible : false ; isOpaque : true ; color_main : Style.errorDialog.text ; color_minor : Style.dialog.textBlue ; }
- ButtonRounded { id : buttonNo ; text : qsTr ( "No" , "Button No" ) ; onClicked : root.clickedNo ( ) ; visible : false ; isOpaque : false ; color_main : Style.errorDialog.text ; color_minor : Style.transparent ; }
- ButtonRounded { id : buttonYes ; text : qsTr ( "Yes" , "Button Yes" ) ; onClicked : root.clickedYes ( ) ; visible : false ; isOpaque : true ; color_main : Style.errorDialog.text ; color_minor : Style.dialog.textBlue ; }
- ButtonRounded { id : buttonRetry ; text : qsTr ( "Retry" , "Button Retry" ) ; onClicked : root.clickedRetry ( ) ; visible : false ; isOpaque : false ; color_main : Style.errorDialog.text ; color_minor : Style.transparent ; }
- ButtonRounded { id : buttonSkip ; text : qsTr ( "Skip" , "Button Skip" ) ; onClicked : root.clickedSkip ( ) ; visible : false ; isOpaque : false ; color_main : Style.errorDialog.text ; color_minor : Style.transparent ; }
- ButtonRounded { id : buttonCancel ; text : qsTr ( "Cancel" , "Button Cancel" ) ; onClicked : root.clickedCancel ( ) ; visible : false ; isOpaque : true ; color_main : Style.errorDialog.text ; color_minor : Style.dialog.textBlue ; }
- ButtonRounded { id : buttonOkay ; text : qsTr ( "Okay" , "Button Okay" ) ; onClicked : root.clickedOkay ( ) ; visible : true ; isOpaque : true ; color_main : Style.errorDialog.text ; color_minor : Style.dialog.textBlue ; }
- }
- }
- }
-
- function show(text) {
- root.text = text
- root.visible = true
- }
-
- function hide() {
- root.visible=false
-
- root .text = ""
- checkbox .text = ""
-
- buttonNo .visible = false
- buttonYes .visible = false
- buttonRetry .visible = false
- buttonSkip .visible = false
- buttonCancel .visible = false
- buttonOkay .visible = true
- }
-}
diff --git a/internal/frontend/qml/ProtonUI/ProgressBar.qml b/internal/frontend/qml/ProtonUI/ProgressBar.qml
deleted file mode 100644
index 9632b56a..00000000
--- a/internal/frontend/qml/ProtonUI/ProgressBar.qml
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
diff --git a/internal/frontend/qml/ProtonUI/RoundedRectangle.qml b/internal/frontend/qml/ProtonUI/RoundedRectangle.qml
deleted file mode 100644
index 2a44c3c4..00000000
--- a/internal/frontend/qml/ProtonUI/RoundedRectangle.qml
+++ /dev/null
@@ -1,115 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-import QtQuick 2.8
-import ProtonUI 1.0
-
-
-Rectangle {
- id: root
-
- color: Style.transparent
-
- property color fillColor : Style.main.background
- property color strokeColor : Style.main.line
- property real strokeWidth : Style.dialog.borderInput
- property real radiusTopLeft : Style.dialog.radiusButton
- property real radiusBottomLeft : Style.dialog.radiusButton
- property real radiusTopRight : Style.dialog.radiusButton
- property real radiusBottomRight : Style.dialog.radiusButton
-
- function paint() {
- canvas.requestPaint()
- }
-
- onFillColorChanged : root.paint()
- onStrokeColorChanged : root.paint()
- onStrokeWidthChanged : root.paint()
- onRadiusTopLeftChanged : root.paint()
- onRadiusBottomLeftChanged : root.paint()
- onRadiusTopRightChanged : root.paint()
- onRadiusBottomRightChanged : root.paint()
-
-
- Canvas {
- id: canvas
- anchors.fill: root
-
- onPaint: {
- var ctx = getContext("2d")
- ctx.clearRect(0, 0, canvas.width, canvas.height);
- ctx.fillStyle = root.fillColor
- ctx.strokeStyle = root.strokeColor
- ctx.lineWidth = root.strokeWidth
- var dimensions = {
- x: ctx.lineWidth,
- y: ctx.lineWidth,
- w: canvas.width-2*ctx.lineWidth,
- h: canvas.height-2*ctx.lineWidth,
- }
- var radius = {
- tl: root.radiusTopLeft,
- tr: root.radiusTopRight,
- bl: root.radiusBottomLeft,
- br: root.radiusBottomRight,
- }
-
- root.roundRect(
- ctx,
- dimensions,
- radius, true, true
- )
- }
- }
-
- // adapted from: https://stackoverflow.com/questions/1255512/how-to-draw-a-rounded-rectangle-on-html-canvas/3368118#3368118
- function roundRect(ctx, dim, radius, fill, stroke) {
- if (typeof stroke == 'undefined') {
- stroke = true;
- }
- if (typeof radius === 'undefined') {
- radius = 5;
- }
- if (typeof radius === 'number') {
- radius = {tl: radius, tr: radius, br: radius, bl: radius};
- } else {
- var defaultRadius = {tl: 0, tr: 0, br: 0, bl: 0};
- for (var side in defaultRadius) {
- radius[side] = radius[side] || defaultRadius[side];
- }
- }
- ctx.beginPath();
- ctx.moveTo(dim.x + radius.tl, dim.y);
- ctx.lineTo(dim.x + dim.w - radius.tr, dim.y);
- ctx.quadraticCurveTo(dim.x + dim.w, dim.y, dim.x + dim.w, dim.y + radius.tr);
- ctx.lineTo(dim.x + dim.w, dim.y + dim.h - radius.br);
- ctx.quadraticCurveTo(dim.x + dim.w, dim.y + dim.h, dim.x + dim.w - radius.br, dim.y + dim.h);
- ctx.lineTo(dim.x + radius.bl, dim.y + dim.h);
- ctx.quadraticCurveTo(dim.x, dim.y + dim.h, dim.x, dim.y + dim.h - radius.bl);
- ctx.lineTo(dim.x, dim.y + radius.tl);
- ctx.quadraticCurveTo(dim.x, dim.y, dim.x + radius.tl, dim.y);
- ctx.closePath();
- if (fill) {
- ctx.fill();
- }
- if (stroke) {
- ctx.stroke();
- }
- }
-
- Component.onCompleted: root.paint()
-}
diff --git a/internal/frontend/qml/ProtonUI/Style.qml b/internal/frontend/qml/ProtonUI/Style.qml
deleted file mode 100644
index 205fa905..00000000
--- a/internal/frontend/qml/ProtonUI/Style.qml
+++ /dev/null
@@ -1,1113 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// colors, fonts, etc.
-pragma Singleton
-import QtQuick 2.8
-
-QtObject {
- // Colors, dimensions and font
-
- property TextMetrics oneInch : TextMetrics { // 72 points is one inch
- id: oneInch
- font.pointSize: 72
- text: "HI"
- }
- property real dpi : oneInch.height // one inch in pixel
- property real refdpi : 96.0
- property real px : dpi/refdpi // default unit, scaled to current DPI
- property real pt : 80 / dpi /// conversion from px to pt (aestetic correction of font size +3 points)
-
- property color transparent: "transparent"
-
- //=================//
- // Stelian //
- //=================//
- // Main window
- property QtObject main : QtObject {
- property color background : "#353440"
- property color text : "#ffffff"
- property color textInactive : "#cdcaf7"
- property color textDisabled : "#bbbbbb"
- property color textBlue : "#9199cc"
- property color textRed : "#ef6a5e"
- property color textGreen : "#41a56c"
- property color textOrange : "#e6922e"
- property color line : "#44444f"
- property real dummy : 10 * px
- property real width : 650 * px
- property real height : 420 * px
- property real heightRow : 54 * px
- property real heightLine : 2 * px
- property real leftMargin : 17 * px
- property real rightMargin : 17 * px
- property real systrayMargin : 20 * px
- property real fontSize : 12 * px
- property real iconSize : 15 * px
- property real leftMarginButton : 9 * px
- property real topMargin : fontSize
- property real bottomMargin : fontSize
- property real border : 1 * px
- }
-
- property QtObject bugreport : QtObject {
- property real width : 645 * px
- property real height : 495 * px
- }
-
- property QtObject errorDialog : QtObject {
- property color background : bubble.background
- property color text : bubble.text
- property real fontSize : dialog.fontSize
- property real radius : 10 * px
- }
-
- property QtObject dialog : QtObject {
- property color background : "#ee353440"
- property color text : "#ffffff"
- property color line : "#505061"
- property color textBlue : "#9396cc"
- property color shadow : "#19505061"
- property real fontSize : 14 * px
- property real titleSize : 17 * px
- property real iconSize : 18 * px
- property real widthButton : 100 * px
- property real heightButton : 3*fontSize
- property real radiusButton : 5 * px
- property real borderButton : 2 * px
- property real borderInput : 1.2 * px
- property real heightSeparator : 21 * px
- property real widthInput : 280 * px
- property real heightInput : 30 * px
- property real heightButtonIcon : 150 * px
- property real widthButtonIcon : 160 * px
- property real rightMargin : 17 * px
- property real bottomMargin : 17 * px
- property real topMargin : 17 * px
- property real leftMargin : 17 * px
- property real heightInputBox : 4*fontSize
- property real widthInputBox : 280 * px
- property real spacing : 5 * px
- }
-
- // Title specific
- property QtObject title : QtObject {
- property color background : "#000"
- property color text : main.text
- property real height : 26 * px
- property real leftMargin : 10 * px
- property real fontSize : 14 * px
- }
-
- property QtObject titleMacOS : QtObject {
- property color background : tabbar.background
- property real height : 22 * px
- property real imgHeight : 12 * px
- property real leftMargin : 8 * px
- property real fontSize : 14 * px
- property real radius : 7 * px
- }
-
- // Tabline specific
- property QtObject tabbar : QtObject {
- property color background : "#302f3a"
- property color text : "#ffffff"
- property color textInactive : "#9696a7"
- property real height : 68 * px
- property real widthButton : 63 * px
- property real heightButton : 38 * px
- property real spacingButton : 35 * px
- property real heightTriangle : 7 * px
- property real fontSize : 12 * px
- property real iconSize : 17 * px
- property real bottomMargin : (height-heightButton)/2
- property real widthUpdate : 138 * px
- property real heightUpdate : 40 * px
- property real leftMargin : main.leftMargin
- property string rightButton : "quit"
- }
-
- // Bubble specific
- property QtObject bubble: QtObject {
- property color background : "#454553"
- property color paneBackground : background
- property color text : dialog.text
- property real height : 185 * px
- property real width : 220 * px
- property real radius : 5 * px
- property real widthPane : 20 * px
- property real iconSize : 14 * px
- property real fontSize : main.fontSize
- }
-
-
- property QtObject menu : QtObject {
- property color background : "#454553"
- property color line : "#505061"
- property color lineAlt : "#565668"
- property color text : "#ffffff"
- property real width : 184 * px
- property real height : 200 * px
- property real radius : 7 * px
- property real topMargin : 21*px + tabbar.height
- property real rightMargin : 24 * px
- //property real heightLine : (width - 2*radius) / 3
- }
-
- property QtObject accounts : QtObject {
- property color line : main.line
- property color backgroundExpanded : "#444456"
- property color backgroundAddrRow : "#1cffffff"
- property real heightLine : main.heightLine
- property real heightHeader : 38 * px
- property real heightAccount : main.heightRow
- property real heightFooter : 75 * px
-
- property real elideWidth : 285 * px
- property real leftMargin2 : 334 * px
- property real leftMargin3 : 463 * px
- property real leftMargin4 : 567 * px
- property real sizeChevron : 9 * px
-
- property real heightAddrRow : 39 * px
- property real heightAddr : 32 * px
- property real leftMarginAddr : 28 * px
- }
-
- property QtObject settings : QtObject {
- property real fontSize : 15 * px
- property real iconSize : 20 * px
- property real toggleSize : 28 * px
- }
-
- property QtObject info : QtObject {
- property real width : 315 * px
- property real height : 450 * px
- property real heightHeader : 32 * px
- property real topMargin : 18 * px
- property real iconSize : 16 * px
- property real leftMarginIcon : 8 * px
- property real widthValue : 180 * px
- }
-
- property QtObject exporting : QtObject {
- property color background : dialog.background
- property color rowBackground : "#f8f8f8"
- property color sliderBackground : "#e6e6e6"
- property color sliderForeground : "#515061"
- property color line : dialog.line
- property color text : "#333"
- property color progressBackground : "#aaa"
- property color progressStatus : main.textBlue // need gradient +- 1.2 light
- property real boxRadius : 5 * px
- property real rowHeight : 32 * px
- property real leftMargin : 5 * px
- property real leftMargin2 : 18 * px
- property real leftMargin3 : 30 * px
- }
-
- property QtObject importing : QtObject {
- property color rowBackground : dialog.background
- property color rowLine : dialog.line
- }
-
- property QtObject dropDownLight: QtObject {
- property color background : dialog.background
- property color text : dialog.text
- property color inactive : dialog.line
- property color highlight : dialog.textBlue
- property color separator : dialog.line
- property color line : dialog.line
- property bool labelBold : true
- }
-
- property QtObject dropDownDark : QtObject {
- property color background : dialog.text
- property color text : dialog.background
- property color inactive : dialog.line
- property color highlight : dialog.textBlue
- property color separator : dialog.line
- property color line : dialog.line
- property bool labelBold : true
- }
-
- property int okInfoBar : 0
- property int warnInfoBar : 1
- property int warnBubbleMessage : 2
- property int errorInfoBar : 4
-
-
-
- // old color pick
- property QtObject old : QtObject {
- /// old scheme
- property color darkBackground: "grey"
- property color darkForground: "red"
- property color darkInactive: "grey"
- property color lightBackground: "white"
- property color lightForground: "grey"
- property color lightInactive: "grey"
- property color linkColor: "blue"
- property color warnColor: "orange"
- //
- property color pm_black: "#000" // pitch black
- property color pm_ddgrey: "#333" // dark background
- property color pm_dgrey: "#555" //
- property color pm_grey: "#999" // inactive dark, lines
- property color pm_white: "#fff" // super white
- property color pm_lgrey: "#acb0bf" // inactive light
- property color pm_llgrey: "#e6eaf0" // light background
- property color pm_blue: "#8286c5"
- property color pm_lblue: "#9397cd"
- property color pm_llblue: "#e3e4f2"
- property color pm_dred: "#c26164"
- property color pm_red: "#af4649"
- property color pm_orange: "#d9c4a2" // warning
- property color pm_lorange: "#e7d360" // warning
- property color pm_green: "#a6cc93" // success
-
- property color web_dark_side_back : "#333333"
- property color web_dark_side_text_inactive : "#999999"
- property color web_dark_highl_back : "#3F3F3F"
- property color web_dark_highl_text : "#FFFFFF"
- property color web_dark_highl_icon : "#A8ABD7"
- property color web_dark_top_back : "#555555"
- property color web_dark_top_icon : "#E9E9E9"
- property color web_butt_blue_back : "#9397CD"
- property color web_butt_blue_text : "#FFFFFF"
- property color web_row_inactive_back : "#DDDDDD"
- property color web_row_inactive_text : "#55556E"
- property color web_butt_grey_text_line : "#838897"
- property color web_butt_grey_text_hover : "#222222"
- property color web_butt_grey_top_back : "#FDFDFD"
- property color web_butt_grey_low_back : "#DEDEDE"
- property color web_main_back : "#FFFFFF"
- property color web_main_text : "#555555"
-
-
- // colors
- property color pmold_dblue: "#333367"
- property color pmold_blue: "#58588c"
- property color pmold_red: "#9e3c3c"
- property color pmold_orange: "#9e7f3c"
- property color pmold_green: "#5e9162"
- property color pmold_gray: "#484a61"
- // highlited
- //property color highlBackground: pm_lblue
- //property color highlForground: pm_dgrey
- //property color highlInactive: pm_grey
- //property color buttLine: pm_grey
- property color buttLight: "#fdfdfd" // button background start
- property color buttDark: "#dedede" // button background start
- }
-
-
- // font
- property FontLoader fontawesome : FontLoader {
- //source: "qrc://fontawesome.ttf"
- source: "fontawesome.ttf"
- }
-
- property QtObject fa : QtObject {
- property string glass : "\uf000"
- property string music : "\uf001"
- property string search : "\uf002"
- property string envelope_o : "\uf003"
- property string heart : "\uf004"
- property string star : "\uf005"
- property string star_o : "\uf006"
- property string user : "\uf007"
- property string film : "\uf008"
- property string th_large : "\uf009"
- property string th : "\uf00a"
- property string th_list : "\uf00b"
- property string check : "\uf00c"
- property string remove : "\uf00d"
- property string close : "\uf00d"
- property string times : "\uf00d"
- property string search_plus : "\uf00e"
- property string search_minus : "\uf010"
- property string power_off : "\uf011"
- property string signal : "\uf012"
- property string gear : "\uf013"
- property string cog : "\uf013"
- property string trash_o : "\uf014"
- property string home : "\uf015"
- property string file_o : "\uf016"
- property string clock_o : "\uf017"
- property string road : "\uf018"
- property string download : "\uf019"
- property string arrow_circle_o_down : "\uf01a"
- property string arrow_circle_o_up : "\uf01b"
- property string inbox : "\uf01c"
- property string play_circle_o : "\uf01d"
- property string rotate_right : "\uf01e"
- property string repeat : "\uf01e"
- property string refresh : "\uf021"
- property string list_alt : "\uf022"
- property string lock : "\uf023"
- property string flag : "\uf024"
- property string headphones : "\uf025"
- property string volume_off : "\uf026"
- property string volume_down : "\uf027"
- property string volume_up : "\uf028"
- property string qrcode : "\uf029"
- property string barcode : "\uf02a"
- property string tag : "\uf02b"
- property string tags : "\uf02c"
- property string book : "\uf02d"
- property string bookmark : "\uf02e"
- property string printer : "\uf02f"
- property string camera : "\uf030"
- property string font : "\uf031"
- property string bold : "\uf032"
- property string italic : "\uf033"
- property string text_height : "\uf034"
- property string text_width : "\uf035"
- property string align_left : "\uf036"
- property string align_center : "\uf037"
- property string align_right : "\uf038"
- property string align_justify : "\uf039"
- property string list : "\uf03a"
- property string dedent : "\uf03b"
- property string outdent : "\uf03b"
- property string indent : "\uf03c"
- property string video_camera : "\uf03d"
- property string photo : "\uf03e"
- property string image : "\uf03e"
- property string picture_o : "\uf03e"
- property string pencil : "\uf040"
- property string map_marker : "\uf041"
- property string adjust : "\uf042"
- property string tint : "\uf043"
- property string edit : "\uf044"
- property string pencil_square_o : "\uf044"
- property string share_square_o : "\uf045"
- property string check_square_o : "\uf046"
- property string arrows : "\uf047"
- property string step_backward : "\uf048"
- property string fast_backward : "\uf049"
- property string backward : "\uf04a"
- property string play : "\uf04b"
- property string pause : "\uf04c"
- property string stop : "\uf04d"
- property string forward : "\uf04e"
- property string fast_forward : "\uf050"
- property string step_forward : "\uf051"
- property string eject : "\uf052"
- property string chevron_left : "\uf053"
- property string chevron_right : "\uf054"
- property string plus_circle : "\uf055"
- property string minus_circle : "\uf056"
- property string times_circle : "\uf057"
- property string check_circle : "\uf058"
- property string question_circle : "\uf059"
- property string info_circle : "\uf05a"
- property string crosshairs : "\uf05b"
- property string times_circle_o : "\uf05c"
- property string check_circle_o : "\uf05d"
- property string ban : "\uf05e"
- property string arrow_left : "\uf060"
- property string arrow_right : "\uf061"
- property string arrow_up : "\uf062"
- property string arrow_down : "\uf063"
- property string mail_forward : "\uf064"
- property string share : "\uf064"
- property string expand : "\uf065"
- property string compress : "\uf066"
- property string plus : "\uf067"
- property string minus : "\uf068"
- property string asterisk : "\uf069"
- property string exclamation_circle : "\uf06a"
- property string gift : "\uf06b"
- property string leaf : "\uf06c"
- property string fire : "\uf06d"
- property string eye : "\uf06e"
- property string eye_slash : "\uf070"
- property string warning : "\uf071"
- property string exclamation_triangle : "\uf071"
- property string plane : "\uf072"
- property string calendar : "\uf073"
- property string random : "\uf074"
- property string comment : "\uf075"
- property string magnet : "\uf076"
- property string chevron_up : "\uf077"
- property string chevron_down : "\uf078"
- property string retweet : "\uf079"
- property string shopping_cart : "\uf07a"
- property string folder : "\uf07b"
- property string folder_open : "\uf07c"
- property string arrows_v : "\uf07d"
- property string arrows_h : "\uf07e"
- property string bar_chart_o : "\uf080"
- property string bar_chart : "\uf080"
- property string twitter_square : "\uf081"
- property string facebook_square : "\uf082"
- property string camera_retro : "\uf083"
- property string key : "\uf084"
- property string gears : "\uf085"
- property string cogs : "\uf085"
- property string comments : "\uf086"
- property string thumbs_o_up : "\uf087"
- property string thumbs_o_down : "\uf088"
- property string star_half : "\uf089"
- property string heart_o : "\uf08a"
- property string sign_out : "\uf08b"
- property string linkedin_square : "\uf08c"
- property string thumb_tack : "\uf08d"
- property string external_link : "\uf08e"
- property string sign_in : "\uf090"
- property string trophy : "\uf091"
- property string github_square : "\uf092"
- property string upload : "\uf093"
- property string lemon_o : "\uf094"
- property string phone : "\uf095"
- property string square_o : "\uf096"
- property string bookmark_o : "\uf097"
- property string phone_square : "\uf098"
- property string twitter : "\uf099"
- property string facebook_f : "\uf09a"
- property string facebook : "\uf09a"
- property string github : "\uf09b"
- property string unlock : "\uf09c"
- property string credit_card : "\uf09d"
- property string feed : "\uf09e"
- property string rss : "\uf09e"
- property string hdd_o : "\uf0a0"
- property string bullhorn : "\uf0a1"
- property string bell : "\uf0f3"
- property string certificate : "\uf0a3"
- property string hand_o_right : "\uf0a4"
- property string hand_o_left : "\uf0a5"
- property string hand_o_up : "\uf0a6"
- property string hand_o_down : "\uf0a7"
- property string arrow_circle_left : "\uf0a8"
- property string arrow_circle_right : "\uf0a9"
- property string arrow_circle_up : "\uf0aa"
- property string arrow_circle_down : "\uf0ab"
- property string globe : "\uf0ac"
- property string wrench : "\uf0ad"
- property string tasks : "\uf0ae"
- property string filter : "\uf0b0"
- property string briefcase : "\uf0b1"
- property string arrows_alt : "\uf0b2"
- property string group : "\uf0c0"
- property string users : "\uf0c0"
- property string chain : "\uf0c1"
- property string link : "\uf0c1"
- property string cloud : "\uf0c2"
- property string flask : "\uf0c3"
- property string cut : "\uf0c4"
- property string scissors : "\uf0c4"
- property string copy : "\uf0c5"
- property string files_o : "\uf0c5"
- property string paperclip : "\uf0c6"
- property string save : "\uf0c7"
- property string floppy_o : "\uf0c7"
- property string square : "\uf0c8"
- property string navicon : "\uf0c9"
- property string reorder : "\uf0c9"
- property string bars : "\uf0c9"
- property string list_ul : "\uf0ca"
- property string list_ol : "\uf0cb"
- property string strikethrough : "\uf0cc"
- property string underline : "\uf0cd"
- property string table : "\uf0ce"
- property string magic : "\uf0d0"
- property string truck : "\uf0d1"
- property string pinterest : "\uf0d2"
- property string pinterest_square : "\uf0d3"
- property string google_plus_square : "\uf0d4"
- property string google_plus : "\uf0d5"
- property string money : "\uf0d6"
- property string caret_down : "\uf0d7"
- property string caret_up : "\uf0d8"
- property string caret_left : "\uf0d9"
- property string caret_right : "\uf0da"
- property string columns : "\uf0db"
- property string unsorted : "\uf0dc"
- property string sort : "\uf0dc"
- property string sort_down : "\uf0dd"
- property string sort_desc : "\uf0dd"
- property string sort_up : "\uf0de"
- property string sort_asc : "\uf0de"
- property string envelope : "\uf0e0"
- property string linkedin : "\uf0e1"
- property string rotate_left : "\uf0e2"
- property string undo : "\uf0e2"
- property string legal : "\uf0e3"
- property string gavel : "\uf0e3"
- property string dashboard : "\uf0e4"
- property string tachometer : "\uf0e4"
- property string comment_o : "\uf0e5"
- property string comments_o : "\uf0e6"
- property string flash : "\uf0e7"
- property string bolt : "\uf0e7"
- property string sitemap : "\uf0e8"
- property string umbrella : "\uf0e9"
- property string paste : "\uf0ea"
- property string clipboard : "\uf0ea"
- property string lightbulb_o : "\uf0eb"
- property string exchange : "\uf0ec"
- property string cloud_download : "\uf0ed"
- property string cloud_upload : "\uf0ee"
- property string user_md : "\uf0f0"
- property string stethoscope : "\uf0f1"
- property string suitcase : "\uf0f2"
- property string bell_o : "\uf0a2"
- property string coffee : "\uf0f4"
- property string cutlery : "\uf0f5"
- property string file_text_o : "\uf0f6"
- property string building_o : "\uf0f7"
- property string hospital_o : "\uf0f8"
- property string ambulance : "\uf0f9"
- property string medkit : "\uf0fa"
- property string fighter_jet : "\uf0fb"
- property string beer : "\uf0fc"
- property string h_square : "\uf0fd"
- property string plus_square : "\uf0fe"
- property string angle_double_left : "\uf100"
- property string angle_double_right : "\uf101"
- property string angle_double_up : "\uf102"
- property string angle_double_down : "\uf103"
- property string angle_left : "\uf104"
- property string angle_right : "\uf105"
- property string angle_up : "\uf106"
- property string angle_down : "\uf107"
- property string desktop : "\uf108"
- property string laptop : "\uf109"
- property string tablet : "\uf10a"
- property string mobile_phone : "\uf10b"
- property string mobile : "\uf10b"
- property string circle_o : "\uf10c"
- property string quote_left : "\uf10d"
- property string quote_right : "\uf10e"
- property string spinner : "\uf110"
- property string circle : "\uf111"
- property string mail_reply : "\uf112"
- property string reply : "\uf112"
- property string github_alt : "\uf113"
- property string folder_o : "\uf114"
- property string folder_open_o : "\uf115"
- property string smile_o : "\uf118"
- property string frown_o : "\uf119"
- property string meh_o : "\uf11a"
- property string gamepad : "\uf11b"
- property string keyboard_o : "\uf11c"
- property string flag_o : "\uf11d"
- property string flag_checkered : "\uf11e"
- property string terminal : "\uf120"
- property string code : "\uf121"
- property string mail_reply_all : "\uf122"
- property string reply_all : "\uf122"
- property string star_half_empty : "\uf123"
- property string star_half_full : "\uf123"
- property string star_half_o : "\uf123"
- property string location_arrow : "\uf124"
- property string crop : "\uf125"
- property string code_fork : "\uf126"
- property string unlink : "\uf127"
- property string chain_broken : "\uf127"
- property string question : "\uf128"
- property string info : "\uf129"
- property string exclamation : "\uf12a"
- property string superscript : "\uf12b"
- property string subscript : "\uf12c"
- property string eraser : "\uf12d"
- property string puzzle_piece : "\uf12e"
- property string microphone : "\uf130"
- property string microphone_slash : "\uf131"
- property string shield : "\uf132"
- property string calendar_o : "\uf133"
- property string fire_extinguisher : "\uf134"
- property string rocket : "\uf135"
- property string maxcdn : "\uf136"
- property string chevron_circle_left : "\uf137"
- property string chevron_circle_right : "\uf138"
- property string chevron_circle_up : "\uf139"
- property string chevron_circle_down : "\uf13a"
- property string html5 : "\uf13b"
- property string css3 : "\uf13c"
- property string anchor : "\uf13d"
- property string unlock_alt : "\uf13e"
- property string bullseye : "\uf140"
- property string ellipsis_h : "\uf141"
- property string ellipsis_v : "\uf142"
- property string rss_square : "\uf143"
- property string play_circle : "\uf144"
- property string ticket : "\uf145"
- property string minus_square : "\uf146"
- property string minus_square_o : "\uf147"
- property string level_up : "\uf148"
- property string level_down : "\uf149"
- property string check_square : "\uf14a"
- property string pencil_square : "\uf14b"
- property string external_link_square : "\uf14c"
- property string share_square : "\uf14d"
- property string compass : "\uf14e"
- property string toggle_down : "\uf150"
- property string caret_square_o_down : "\uf150"
- property string toggle_up : "\uf151"
- property string caret_square_o_up : "\uf151"
- property string toggle_right : "\uf152"
- property string caret_square_o_right : "\uf152"
- property string euro : "\uf153"
- property string eur : "\uf153"
- property string gbp : "\uf154"
- property string dollar : "\uf155"
- property string usd : "\uf155"
- property string rupee : "\uf157"
- property string inr : "\uf156"
- property string cny : "\uf157"
- property string rmb : "\uf157"
- property string yen : "\uf157"
- property string jpy : "\uf157"
- property string ruble : "\uf158"
- property string rouble : "\uf158"
- property string rub : "\uf158"
- property string won : "\uf159"
- property string krw : "\uf159"
- property string bitcoin : "\uf15a"
- property string btc : "\uf15a"
- property string file : "\uf15b"
- property string file_text : "\uf15c"
- property string sort_alpha_asc : "\uf15d"
- property string sort_alpha_desc : "\uf15e"
- property string sort_amount_asc : "\uf160"
- property string sort_amount_desc : "\uf161"
- property string sort_numeric_asc : "\uf162"
- property string sort_numeric_desc : "\uf163"
- property string thumbs_up : "\uf164"
- property string thumbs_down : "\uf165"
- property string youtube_square : "\uf166"
- property string youtube : "\uf167"
- property string xing : "\uf168"
- property string xing_square : "\uf169"
- property string youtube_play : "\uf16a"
- property string dropbox : "\uf16b"
- property string stack_overflow : "\uf16c"
- property string instagram : "\uf16d"
- property string flickr : "\uf16e"
- property string adn : "\uf170"
- property string bitbucket : "\uf171"
- property string bitbucket_square : "\uf172"
- property string tumblr : "\uf173"
- property string tumblr_square : "\uf174"
- property string long_arrow_down : "\uf175"
- property string long_arrow_up : "\uf176"
- property string long_arrow_left : "\uf177"
- property string long_arrow_right : "\uf178"
- property string apple : "\uf179"
- property string windows : "\uf17a"
- property string android : "\uf17b"
- property string linux : "\uf17c"
- property string dribbble : "\uf17d"
- property string skype : "\uf17e"
- property string foursquare : "\uf180"
- property string trello : "\uf181"
- property string female : "\uf182"
- property string male : "\uf183"
- property string gittip : "\uf184"
- property string gratipay : "\uf184"
- property string sun_o : "\uf185"
- property string moon_o : "\uf186"
- property string archive : "\uf187"
- property string bug : "\uf188"
- property string vk : "\uf189"
- property string weibo : "\uf18a"
- property string renren : "\uf18b"
- property string pagelines : "\uf18c"
- property string stack_exchange : "\uf18d"
- property string arrow_circle_o_right : "\uf18e"
- property string arrow_circle_o_left : "\uf190"
- property string toggle_left : "\uf191"
- property string caret_square_o_left : "\uf191"
- property string dot_circle_o : "\uf192"
- property string wheelchair : "\uf193"
- property string vimeo_square : "\uf194"
- property string turkish_lira : "\uf195"
- property string fa_try : "\uf195"
- property string plus_square_o : "\uf196"
- property string space_shuttle : "\uf197"
- property string slack : "\uf198"
- property string envelope_square : "\uf199"
- property string wordpress : "\uf19a"
- property string openid : "\uf19b"
- property string institution : "\uf19c"
- property string bank : "\uf19c"
- property string university : "\uf19c"
- property string mortar_board : "\uf19d"
- property string graduation_cap : "\uf19d"
- property string yahoo : "\uf19e"
- property string google : "\uf1a0"
- property string reddit : "\uf1a1"
- property string reddit_square : "\uf1a2"
- property string stumbleupon_circle : "\uf1a3"
- property string stumbleupon : "\uf1a4"
- property string delicious : "\uf1a5"
- property string digg : "\uf1a6"
- property string pied_piper_pp : "\uf1a7"
- property string pied_piper_alt : "\uf1a8"
- property string drupal : "\uf1a9"
- property string joomla : "\uf1aa"
- property string language : "\uf1ab"
- property string fax : "\uf1ac"
- property string building : "\uf1ad"
- property string child : "\uf1ae"
- property string paw : "\uf1b0"
- property string spoon : "\uf1b1"
- property string cube : "\uf1b2"
- property string cubes : "\uf1b3"
- property string behance : "\uf1b4"
- property string behance_square : "\uf1b5"
- property string steam : "\uf1b6"
- property string steam_square : "\uf1b7"
- property string recycle : "\uf1b8"
- property string automobile : "\uf1b9"
- property string car : "\uf1b9"
- property string cab : "\uf1ba"
- property string taxi : "\uf1ba"
- property string tree : "\uf1bb"
- property string spotify : "\uf1bc"
- property string deviantart : "\uf1bd"
- property string soundcloud : "\uf1be"
- property string database : "\uf1c0"
- property string file_pdf_o : "\uf1c1"
- property string file_word_o : "\uf1c2"
- property string file_excel_o : "\uf1c3"
- property string file_powerpoint_o : "\uf1c4"
- property string file_photo_o : "\uf1c5"
- property string file_picture_o : "\uf1c5"
- property string file_image_o : "\uf1c5"
- property string file_zip_o : "\uf1c6"
- property string file_archive_o : "\uf1c6"
- property string file_sound_o : "\uf1c7"
- property string file_audio_o : "\uf1c7"
- property string file_movie_o : "\uf1c8"
- property string file_video_o : "\uf1c8"
- property string file_code_o : "\uf1c9"
- property string vine : "\uf1ca"
- property string codepen : "\uf1cb"
- property string jsfiddle : "\uf1cc"
- property string life_bouy : "\uf1cd"
- property string life_buoy : "\uf1cd"
- property string life_saver : "\uf1cd"
- property string support : "\uf1cd"
- property string life_ring : "\uf1cd"
- property string circle_o_notch : "\uf1ce"
- property string ra : "\uf1d0"
- property string resistance : "\uf1d0"
- property string rebel : "\uf1d0"
- property string ge : "\uf1d1"
- property string empire : "\uf1d1"
- property string git_square : "\uf1d2"
- property string git : "\uf1d3"
- property string y_combinator_square : "\uf1d4"
- property string yc_square : "\uf1d4"
- property string hacker_news : "\uf1d4"
- property string tencent_weibo : "\uf1d5"
- property string qq : "\uf1d6"
- property string wechat : "\uf1d7"
- property string weixin : "\uf1d7"
- property string send : "\uf1d8"
- property string paper_plane : "\uf1d8"
- property string send_o : "\uf1d9"
- property string paper_plane_o : "\uf1d9"
- property string history : "\uf1da"
- property string circle_thin : "\uf1db"
- property string header : "\uf1dc"
- property string paragraph : "\uf1dd"
- property string sliders : "\uf1de"
- property string share_alt : "\uf1e0"
- property string share_alt_square : "\uf1e1"
- property string bomb : "\uf1e2"
- property string soccer_ball_o : "\uf1e3"
- property string futbol_o : "\uf1e3"
- property string tty : "\uf1e4"
- property string binoculars : "\uf1e5"
- property string plug : "\uf1e6"
- property string slideshare : "\uf1e7"
- property string twitch : "\uf1e8"
- property string yelp : "\uf1e9"
- property string newspaper_o : "\uf1ea"
- property string wifi : "\uf1eb"
- property string calculator : "\uf1ec"
- property string paypal : "\uf1ed"
- property string google_wallet : "\uf1ee"
- property string cc_visa : "\uf1f0"
- property string cc_mastercard : "\uf1f1"
- property string cc_discover : "\uf1f2"
- property string cc_amex : "\uf1f3"
- property string cc_paypal : "\uf1f4"
- property string cc_stripe : "\uf1f5"
- property string bell_slash : "\uf1f6"
- property string bell_slash_o : "\uf1f7"
- property string trash : "\uf1f8"
- property string copyright : "\uf1f9"
- property string at : "\uf1fa"
- property string eyedropper : "\uf1fb"
- property string paint_brush : "\uf1fc"
- property string birthday_cake : "\uf1fd"
- property string area_chart : "\uf1fe"
- property string pie_chart : "\uf200"
- property string line_chart : "\uf201"
- property string lastfm : "\uf202"
- property string lastfm_square : "\uf203"
- property string toggle_off : "\uf204"
- property string toggle_on : "\uf205"
- property string bicycle : "\uf206"
- property string bus : "\uf207"
- property string ioxhost : "\uf208"
- property string angellist : "\uf209"
- property string cc : "\uf20a"
- property string shekel : "\uf20b"
- property string sheqel : "\uf20b"
- property string ils : "\uf20b"
- property string meanpath : "\uf20c"
- property string buysellads : "\uf20d"
- property string connectdevelop : "\uf20e"
- property string dashcube : "\uf210"
- property string forumbee : "\uf211"
- property string leanpub : "\uf212"
- property string sellsy : "\uf213"
- property string shirtsinbulk : "\uf214"
- property string simplybuilt : "\uf215"
- property string skyatlas : "\uf216"
- property string cart_plus : "\uf217"
- property string cart_arrow_down : "\uf218"
- property string diamond : "\uf219"
- property string ship : "\uf21a"
- property string user_secret : "\uf21b"
- property string motorcycle : "\uf21c"
- property string street_view : "\uf21d"
- property string heartbeat : "\uf21e"
- property string venus : "\uf221"
- property string mars : "\uf222"
- property string mercury : "\uf223"
- property string intersex : "\uf224"
- property string transgender : "\uf224"
- property string transgender_alt : "\uf225"
- property string venus_double : "\uf226"
- property string mars_double : "\uf227"
- property string venus_mars : "\uf228"
- property string mars_stroke : "\uf229"
- property string mars_stroke_v : "\uf22a"
- property string mars_stroke_h : "\uf22b"
- property string neuter : "\uf22c"
- property string genderless : "\uf22d"
- property string facebook_official : "\uf230"
- property string pinterest_p : "\uf231"
- property string whatsapp : "\uf232"
- property string server : "\uf233"
- property string user_plus : "\uf234"
- property string user_times : "\uf235"
- property string hotel : "\uf236"
- property string bed : "\uf236"
- property string viacoin : "\uf237"
- property string train : "\uf238"
- property string subway : "\uf239"
- property string medium : "\uf23a"
- property string yc : "\uf23b"
- property string y_combinator : "\uf23b"
- property string optin_monster : "\uf23c"
- property string opencart : "\uf23d"
- property string expeditedssl : "\uf23e"
- property string battery_4 : "\uf240"
- property string battery : "\uf240"
- property string battery_full : "\uf240"
- property string battery_3 : "\uf241"
- property string battery_three_quarters : "\uf241"
- property string battery_2 : "\uf242"
- property string battery_half : "\uf242"
- property string battery_1 : "\uf243"
- property string battery_quarter : "\uf243"
- property string battery_0 : "\uf244"
- property string battery_empty : "\uf244"
- property string mouse_pointer : "\uf245"
- property string i_cursor : "\uf246"
- property string object_group : "\uf247"
- property string object_ungroup : "\uf248"
- property string sticky_note : "\uf249"
- property string sticky_note_o : "\uf24a"
- property string cc_jcb : "\uf24b"
- property string cc_diners_club : "\uf24c"
- property string clone : "\uf24d"
- property string balance_scale : "\uf24e"
- property string hourglass_o : "\uf250"
- property string hourglass_1 : "\uf251"
- property string hourglass_start : "\uf251"
- property string hourglass_2 : "\uf252"
- property string hourglass_half : "\uf252"
- property string hourglass_3 : "\uf253"
- property string hourglass_end : "\uf253"
- property string hourglass : "\uf254"
- property string hand_grab_o : "\uf255"
- property string hand_rock_o : "\uf255"
- property string hand_stop_o : "\uf256"
- property string hand_paper_o : "\uf256"
- property string hand_scissors_o : "\uf257"
- property string hand_lizard_o : "\uf258"
- property string hand_spock_o : "\uf259"
- property string hand_pointer_o : "\uf25a"
- property string hand_peace_o : "\uf25b"
- property string trademark : "\uf25c"
- property string registered : "\uf25d"
- property string creative_commons : "\uf25e"
- property string gg : "\uf260"
- property string gg_circle : "\uf261"
- property string tripadvisor : "\uf262"
- property string odnoklassniki : "\uf263"
- property string odnoklassniki_square : "\uf264"
- property string get_pocket : "\uf265"
- property string wikipedia_w : "\uf266"
- property string safari : "\uf267"
- property string chrome : "\uf268"
- property string firefox : "\uf269"
- property string opera : "\uf26a"
- property string internet_explorer : "\uf26b"
- property string tv : "\uf26c"
- property string television : "\uf26c"
- property string contao : "\uf26d"
- property string fa_500px : "\uf26e"
- property string amazon : "\uf270"
- property string calendar_plus_o : "\uf271"
- property string calendar_minus_o : "\uf272"
- property string calendar_times_o : "\uf273"
- property string calendar_check_o : "\uf274"
- property string industry : "\uf275"
- property string map_pin : "\uf276"
- property string map_signs : "\uf277"
- property string map_o : "\uf278"
- property string map : "\uf279"
- property string commenting : "\uf27a"
- property string commenting_o : "\uf27b"
- property string houzz : "\uf27c"
- property string vimeo : "\uf27d"
- property string black_tie : "\uf27e"
- property string fonticons : "\uf280"
- property string reddit_alien : "\uf281"
- property string edge : "\uf282"
- property string credit_card_alt : "\uf283"
- property string codiepie : "\uf284"
- property string modx : "\uf285"
- property string fort_awesome : "\uf286"
- property string usb : "\uf287"
- property string product_hunt : "\uf288"
- property string mixcloud : "\uf289"
- property string scribd : "\uf28a"
- property string pause_circle : "\uf28b"
- property string pause_circle_o : "\uf28c"
- property string stop_circle : "\uf28d"
- property string stop_circle_o : "\uf28e"
- property string shopping_bag : "\uf290"
- property string shopping_basket : "\uf291"
- property string hashtag : "\uf292"
- property string bluetooth : "\uf293"
- property string bluetooth_b : "\uf294"
- property string percent : "\uf295"
- property string gitlab : "\uf296"
- property string wpbeginner : "\uf297"
- property string wpforms : "\uf298"
- property string envira : "\uf299"
- property string universal_access : "\uf29a"
- property string wheelchair_alt : "\uf29b"
- property string question_circle_o : "\uf29c"
- property string blind : "\uf29d"
- property string audio_description : "\uf29e"
- property string volume_control_phone : "\uf2a0"
- property string braille : "\uf2a1"
- property string assistive_listening_systems : "\uf2a2"
- property string asl_interpreting : "\uf2a3"
- property string american_sign_language_interpreting : "\uf2a3"
- property string deafness : "\uf2a4"
- property string hard_of_hearing : "\uf2a4"
- property string deaf : "\uf2a4"
- property string glide : "\uf2a5"
- property string glide_g : "\uf2a6"
- property string signing : "\uf2a7"
- property string sign_language : "\uf2a7"
- property string low_vision : "\uf2a8"
- property string viadeo : "\uf2a9"
- property string viadeo_square : "\uf2aa"
- property string snapchat : "\uf2ab"
- property string snapchat_ghost : "\uf2ac"
- property string snapchat_square : "\uf2ad"
- property string pied_piper : "\uf2ae"
- property string first_order : "\uf2b0"
- property string yoast : "\uf2b1"
- property string themeisle : "\uf2b2"
- property string google_plus_circle : "\uf2b3"
- property string google_plus_official : "\uf2b3"
- property string fa : "\uf2b4"
- property string font_awesome : "\uf2b4"
- property string handshake_o : "\uf2b5"
- property string envelope_open : "\uf2b6"
- property string envelope_open_o : "\uf2b7"
- property string linode : "\uf2b8"
- property string address_book : "\uf2b9"
- property string address_book_o : "\uf2ba"
- property string vcard : "\uf2bb"
- property string address_card : "\uf2bb"
- property string vcard_o : "\uf2bc"
- property string address_card_o : "\uf2bc"
- property string user_circle : "\uf2bd"
- property string user_circle_o : "\uf2be"
- property string user_o : "\uf2c0"
- property string id_badge : "\uf2c1"
- property string drivers_license : "\uf2c2"
- property string id_card : "\uf2c2"
- property string drivers_license_o : "\uf2c3"
- property string id_card_o : "\uf2c3"
- property string quora : "\uf2c4"
- property string free_code_camp : "\uf2c5"
- property string telegram : "\uf2c6"
- property string thermometer_4 : "\uf2c7"
- property string thermometer : "\uf2c7"
- property string thermometer_full : "\uf2c7"
- property string thermometer_3 : "\uf2c8"
- property string thermometer_three_quarters : "\uf2c8"
- property string thermometer_2 : "\uf2c9"
- property string thermometer_half : "\uf2c9"
- property string thermometer_1 : "\uf2ca"
- property string thermometer_quarter : "\uf2ca"
- property string thermometer_0 : "\uf2cb"
- property string thermometer_empty : "\uf2cb"
- property string shower : "\uf2cc"
- property string bathtub : "\uf2cd"
- property string s15 : "\uf2cd"
- property string bath : "\uf2cd"
- property string podcast : "\uf2ce"
- property string window_maximize : "\uf2d0"
- property string window_minimize : "\uf2d1"
- property string window_restore : "\uf2d2"
- property string times_rectangle : "\uf2d3"
- property string window_close : "\uf2d3"
- property string times_rectangle_o : "\uf2d4"
- property string window_close_o : "\uf2d4"
- property string bandcamp : "\uf2d5"
- property string grav : "\uf2d6"
- property string etsy : "\uf2d7"
- property string imdb : "\uf2d8"
- property string ravelry : "\uf2d9"
- property string eercast : "\uf2da"
- property string microchip : "\uf2db"
- property string snowflake_o : "\uf2dc"
- property string superpowers : "\uf2dd"
- property string wpexplorer : "\uf2de"
- property string meetup : "\uf2e0"
- }
-}
diff --git a/internal/frontend/qml/ProtonUI/TLSCertPinIssueBar.qml b/internal/frontend/qml/ProtonUI/TLSCertPinIssueBar.qml
deleted file mode 100644
index 5d1aceff..00000000
--- a/internal/frontend/qml/ProtonUI/TLSCertPinIssueBar.qml
+++ /dev/null
@@ -1,69 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// Important information under title bar
-
-import QtQuick 2.8
-import QtQuick.Window 2.2
-import QtQuick.Controls 2.1
-import ProtonUI 1.0
-
-Rectangle {
- id: root
- height: 0
- visible: state != "ok"
- state: "ok"
- color: "black"
- property var fontSize : 1.0 * Style.main.fontSize
-
- Row {
- anchors.centerIn: root
- visible: root.visible
- spacing: Style.main.leftMarginButton
-
- AccessibleText {
- id: message
- font.pointSize: root.fontSize * Style.pt
-
- text: qsTr("Connection security error: Your network connection to Proton services may be insecure.", "message in bar showed when TLS Pinning fails")
- }
-
- ClickIconText {
- anchors.verticalCenter : message.verticalCenter
- iconText : ""
- text : qsTr("Learn more", "This button opens TLS Pinning issue modal with more explanation")
- visible : root.visible
- onClicked : {
- winMain.dialogTlsCert.show()
- }
- fontSize : root.fontSize
- textUnderline: true
- }
- }
-
-
- states: [
- State {
- name: "notOK"
- PropertyChanges {
- target: root
- height: 2* Style.main.fontSize
- color: Style.main.textRed
- }
- }
- ]
-}
diff --git a/internal/frontend/qml/ProtonUI/TabButton.qml b/internal/frontend/qml/ProtonUI/TabButton.qml
deleted file mode 100644
index 805e68c3..00000000
--- a/internal/frontend/qml/ProtonUI/TabButton.qml
+++ /dev/null
@@ -1,103 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// Button with text and icon for tabbar
-
-import QtQuick 2.8
-import ProtonUI 1.0
-import QtQuick.Controls 2.1
-
-AccessibleButton {
- id: root
- property alias iconText : icon.text
- property alias title : titleText.text
- property color textColor : {
- if (root.state=="deactivated") {
- return Qt.lighter(Style.tabbar.textInactive, root.hovered || root.activeFocus ? 1.25 : 1.0)
- }
- if (root.state=="activated") {
- return Style.tabbar.text
- }
- }
-
- text: root.title
- Accessible.description: root.title + " tab"
-
- width : titleMetrics.width // Style.tabbar.widthButton
- height : Style.tabbar.heightButton
- padding: 0
-
- background: Rectangle {
- color : Style.transparent
-
- MouseArea {
- anchors.fill: parent
- cursorShape: Qt.PointingHandCursor
- acceptedButtons: Qt.NoButton
- }
- }
-
- contentItem : Rectangle {
- color: "transparent"
- scale : root.pressed ? 0.96 : 1.00
-
- Text {
- id: icon
- // dimenstions
- anchors {
- top : parent.top
- horizontalCenter : parent.horizontalCenter
- }
- // style
- color : root.textColor
- font {
- family : Style.fontawesome.name
- pointSize : Style.tabbar.iconSize * Style.pt
- }
- }
-
- TextMetrics {
- id: titleMetrics
- text : root.title
- font.pointSize : titleText.font.pointSize
- }
-
- Text {
- id: titleText
- // dimenstions
- anchors {
- bottom : parent.bottom
- horizontalCenter : parent.horizontalCenter
- }
- // style
- color : root.textColor
- font {
- pointSize : Style.tabbar.fontSize * Style.pt
- bold : root.state=="activated"
- }
- }
- }
-
- states: [
- State {
- name: "activated"
- },
- State {
- name: "deactivated"
- }
- ]
-}
diff --git a/internal/frontend/qml/ProtonUI/TabLabels.qml b/internal/frontend/qml/ProtonUI/TabLabels.qml
deleted file mode 100644
index 3e640049..00000000
--- a/internal/frontend/qml/ProtonUI/TabLabels.qml
+++ /dev/null
@@ -1,107 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// Tab labels
-
-import QtQuick 2.8
-import ProtonUI 1.0
-
-
-Rectangle {
- id: root
- // attributes
- property alias model : tablist.model
- property alias currentIndex : tablist.currentIndex
- property int spacing : Style.tabbar.widthButton + Style.tabbar.spacingButton
- currentIndex: 0
-
- // appereance
- height : Style.tabbar.height
- color : Style.tabbar.background
-
- // content
- ListView {
- id: tablist
- // dimensions
- anchors {
- fill: root
- leftMargin : Style.tabbar.leftMargin
- rightMargin : Style.main.rightMargin
- bottomMargin : Style.tabbar.bottomMargin
- }
- spacing: Style.tabbar.spacingButton
- interactive : false
- // style
- orientation: Qt.Horizontal
- delegate: TabButton {
- anchors.bottom : parent.bottom
- title : modelData.title
- iconText : modelData.iconText
- state : index == tablist.currentIndex ? "activated" : "deactivated"
- onClicked : {
- tablist.currentIndex = index
- }
- }
- }
-
- // Quit button
- TabButton {
- id: buttonQuit
- title : qsTr("Close Bridge", "quits the application")
- iconText : Style.fa.power_off
- state : "deactivated"
- visible : Style.tabbar.rightButton=="quit"
- anchors {
- right : root.right
- bottom : root.bottom
- rightMargin : Style.main.rightMargin
- bottomMargin : Style.tabbar.bottomMargin
- }
-
- Accessible.description: buttonQuit.title
-
- onClicked : {
- dialogGlobal.state = "quit"
- dialogGlobal.show()
- }
- }
-
- // Add account
- TabButton {
- id: buttonAddAccount
- title : qsTr("Add account", "start the authentication to add account")
- iconText : Style.fa.plus_circle
- state : "deactivated"
- visible : Style.tabbar.rightButton=="add account"
- anchors {
- right : root.right
- bottom : root.bottom
- rightMargin : Style.main.rightMargin
- bottomMargin : Style.tabbar.bottomMargin
- }
-
- Accessible.description: buttonAddAccount.title
-
- onClicked : dialogAddUser.show()
- }
-
- function focusButton() {
- tablist.currentItem.forceActiveFocus()
- tablist.currentItem.Accessible.focusedChanged(true)
- }
-}
-
diff --git a/internal/frontend/qml/ProtonUI/TextLabel.qml b/internal/frontend/qml/ProtonUI/TextLabel.qml
deleted file mode 100644
index cc0f8c52..00000000
--- a/internal/frontend/qml/ProtonUI/TextLabel.qml
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-import QtQuick 2.8
-import ProtonUI 1.0
-
-AccessibleText{
- id: root
- property bool hasCopyButton : false
- font.pointSize: Style.main.fontSize * Style.pt
- state: "label"
-
- states : [
- State {
- name: "label"
- PropertyChanges {
- target : root
- font.bold : false
- color : Style.main.textDisabled
- }
- },
- State {
- name: "heading"
- PropertyChanges {
- target : root
- font.bold : true
- color : Style.main.textDisabled
- }
- }
- ]
-}
diff --git a/internal/frontend/qml/ProtonUI/TextValue.qml b/internal/frontend/qml/ProtonUI/TextValue.qml
deleted file mode 100644
index a3560375..00000000
--- a/internal/frontend/qml/ProtonUI/TextValue.qml
+++ /dev/null
@@ -1,85 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-import QtQuick 2.8
-import ProtonUI 1.0
-
-Rectangle {
- id: root
- property string text: "undef"
- width: copyIcon.width + valueText.width
- height: Math.max(copyIcon.height, valueText.contentHeight)
- color: "transparent"
-
- Rectangle {
- id: copyIcon
- width: Style.info.leftMarginIcon*2 + Style.info.iconSize
- height : Style.info.iconSize
- color: "transparent"
- anchors {
- top: root.top
- left: root.left
- }
- Text {
- anchors.centerIn: parent
- font {
- pointSize : Style.info.iconSize * Style.pt
- family : Style.fontawesome.name
- }
- color : Style.main.textInactive
- text: Style.fa.copy
- }
- MouseArea {
- anchors.fill: parent
- onClicked : {
- valueText.select(0, valueText.length)
- valueText.copy()
- valueText.deselect()
- }
- onPressed: copyIcon.scale = 0.90
- onReleased: copyIcon.scale = 1
- }
-
- Accessible.role: Accessible.Button
- Accessible.name: qsTr("Copy %1 to clipboard", "Click to copy the value to system clipboard.").arg(root.text)
- Accessible.description: Accessible.name
- }
-
- TextEdit {
- id: valueText
- width: Style.info.widthValue
- height: Style.main.fontSize
- anchors {
- top: root.top
- left: copyIcon.right
- }
- font {
- pointSize: Style.main.fontSize * Style.pt
- }
- color: Style.main.text
- readOnly: true
- selectByMouse: true
- selectByKeyboard: true
- wrapMode: TextEdit.Wrap
- text: root.text
- selectionColor: Style.dialog.textBlue
-
- Accessible.role: Accessible.StaticText
- Accessible.name: root.text
- Accessible.description: Accessible.name
- }
-}
diff --git a/internal/frontend/qml/ProtonUI/WindowTitleBar.qml b/internal/frontend/qml/ProtonUI/WindowTitleBar.qml
deleted file mode 100644
index b03d2a9f..00000000
--- a/internal/frontend/qml/ProtonUI/WindowTitleBar.qml
+++ /dev/null
@@ -1,350 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// simulating window title bar with different color
-
-import QtQuick 2.8
-import QtQuick.Window 2.2
-import ProtonUI 1.0
-
-Rectangle {
- id: root
- height: visible ? (
- root.isDarwin ? Style.titleMacOS.height : Style.title.height
- ) : 0
- color: "transparent"
- property bool isDarwin : (go.goos == "darwin")
- property QtObject window
- anchors {
- left : parent.left
- right : parent.right
- top : parent.top
- }
-
- MouseArea {
- property point diff: "0,0"
- anchors {
- top: root.top
- bottom: root.bottom
- left: root.left
- right: root.isDarwin ? root.right : iconRowWin.left
- }
- onPressed: {
- diff = Qt.point(window.x, window.y)
- var mousePos = mapToGlobal(mouse.x, mouse.y)
- diff.x -= mousePos.x
- diff.y -= mousePos.y
- }
- onPositionChanged: {
- var currPos = mapToGlobal(mouse.x, mouse.y)
- window.x = currPos.x + diff.x
- window.y = currPos.y + diff.y
- }
- }
-
- // top background
- Rectangle {
- id: upperBackground
- anchors.fill: root
- color: (isDarwin? Style.titleMacOS.background : Style.title.background )
- radius: (isDarwin? Style.titleMacOS.radius : 0)
- border {
- width: Style.main.border
- color: Style.title.background
- }
- }
- // bottom background
- Rectangle {
- id: lowerBorder
- anchors {
- top: root.verticalCenter
- left: root.left
- right: root.right
- bottom: root.bottom
- }
- color: Style.title.background
- Rectangle {
- id: lowerBackground
- anchors{
- fill : parent
- leftMargin : Style.main.border
- rightMargin : Style.main.border
- }
- color: upperBackground.color
-
- }
- }
-
- // Title
- TextMetrics {
- id: titleMetrics
- text : window.title
- font : isDarwin ? titleMac.font : titleWin.font
- elide: Qt.ElideMiddle
- elideWidth : window.width/2
- }
- Text {
- id: titleWin
- visible: !isDarwin
- anchors {
- baseline : logo.bottom
- left : logo.right
- leftMargin : Style.title.leftMargin/1.5
- }
- color : window.active ? Style.title.text : Style.main.textDisabled
- text : titleMetrics.elidedText
- font.pointSize : Style.main.fontSize * Style.pt
- }
- Text {
- id: titleMac
- visible: isDarwin
- anchors {
- verticalCenter : parent.verticalCenter
- left : parent.left
- leftMargin : (parent.width-width)/2
- }
- color : window.active ? Style.title.text : Style.main.textDisabled
- text : titleMetrics.elidedText
- font.pointSize : Style.main.fontSize * Style.pt
- }
-
-
- // MACOS
- MouseArea {
- anchors.fill: iconRowMac
- property string beforeHover
- hoverEnabled: true
- onEntered: {
- beforeHover=iconRed.state
- //iconYellow.state="hover"
- iconRed.state="hover"
- }
- onExited: {
- //iconYellow.state=beforeHover
- iconRed.state=beforeHover
- }
- }
- Connections {
- target: window
- onActiveChanged : {
- if (window.active) {
- //iconYellow.state="normal"
- iconRed.state="normal"
- } else {
- //iconYellow.state="disabled"
- iconRed.state="disabled"
- }
- }
- }
- Row {
- id: iconRowMac
- visible : isDarwin
- spacing : Style.titleMacOS.leftMargin
- anchors {
- left : parent.left
- verticalCenter : parent.verticalCenter
- leftMargin : Style.title.leftMargin
- }
- Image {
- id: iconRed
- width : Style.titleMacOS.imgHeight
- height : Style.titleMacOS.imgHeight
- fillMode : Image.PreserveAspectFit
- smooth : true
- state : "normal"
- states: [
- State { name: "normal" ; PropertyChanges { target: iconRed ; source: "images/macos_red.png" } },
- State { name: "hover" ; PropertyChanges { target: iconRed ; source: "images/macos_red_hl.png" } },
- State { name: "pressed" ; PropertyChanges { target: iconRed ; source: "images/macos_red_dark.png" } },
- State { name: "disabled" ; PropertyChanges { target: iconRed ; source: "images/macos_gray.png" } }
- ]
- MouseArea {
- anchors.fill: parent
- property string beforePressed : "normal"
- onClicked : {
- window.close()
- }
- onPressed: {
- beforePressed = parent.state
- parent.state="pressed"
- }
- onReleased: {
- parent.state=beforePressed
- }
- Accessible.role: Accessible.Button
- Accessible.name: qsTr("Close", "Close the window button")
- Accessible.description: Accessible.name
- Accessible.ignored: !parent.visible
- Accessible.onPressAction: {
- window.close()
- }
- }
- }
- Image {
- id: iconYellow
- width : Style.titleMacOS.imgHeight
- height : Style.titleMacOS.imgHeight
- fillMode : Image.PreserveAspectFit
- smooth : true
- state : "disabled"
- states: [
- State { name: "normal" ; PropertyChanges { target: iconYellow ; source: "images/macos_yellow.png" } },
- State { name: "hover" ; PropertyChanges { target: iconYellow ; source: "images/macos_yellow_hl.png" } },
- State { name: "pressed" ; PropertyChanges { target: iconYellow ; source: "images/macos_yellow_dark.png" } },
- State { name: "disabled" ; PropertyChanges { target: iconYellow ; source: "images/macos_gray.png" } }
- ]
- /*
- MouseArea {
- anchors.fill: parent
- property string beforePressed : "normal"
- onClicked : {
- window.visibility = Window.Minimized
- }
- onPressed: {
- beforePressed = parent.state
- parent.state="pressed"
- }
- onReleased: {
- parent.state=beforePressed
- }
-
- Accessible.role: Accessible.Button
- Accessible.name: qsTr("Minimize", "Minimize the window button")
- Accessible.description: Accessible.name
- Accessible.ignored: !parent.visible
- Accessible.onPressAction: {
- window.visibility = Window.Minimized
- }
- }
- */
- }
- Image {
- id: iconGreen
- width : Style.titleMacOS.imgHeight
- height : Style.titleMacOS.imgHeight
- fillMode : Image.PreserveAspectFit
- smooth : true
- source : "images/macos_gray.png"
- Component.onCompleted : {
- visible = false // (window.flags&Qt.Dialog) != Qt.Dialog
- }
- }
- }
-
-
- // Windows
- Image {
- id: logo
- visible: !isDarwin
- anchors {
- left : parent.left
- verticalCenter : parent.verticalCenter
- leftMargin : Style.title.leftMargin
- }
- height : Style.title.fontSize-2*Style.px
- fillMode : Image.PreserveAspectFit
- mipmap : true
- source : "images/pm_logo.png"
- }
-
- Row {
- id: iconRowWin
- visible: !isDarwin
- anchors {
- right : parent.right
- verticalCenter : root.verticalCenter
- }
- Rectangle {
- height : root.height
- width : 1.5*height
- color: Style.transparent
- Image {
- id: iconDash
- anchors.centerIn: parent
- height : iconTimes.height*0.90
- fillMode : Image.PreserveAspectFit
- mipmap : true
- source : "images/win10_Dash.png"
- }
- MouseArea {
- anchors.fill : parent
- hoverEnabled : true
- onClicked : {
- window.visibility = Window.Minimized
- }
- onPressed: {
- parent.scale=0.92
- }
- onReleased: {
- parent.scale=1
- }
- onEntered: {
- parent.color= Qt.lighter(Style.title.background,1.2)
- }
- onExited: {
- parent.color=Style.transparent
- }
-
- Accessible.role : Accessible.Button
- Accessible.name : qsTr("Minimize", "Minimize the window button")
- Accessible.description : Accessible.name
- Accessible.ignored : !parent.visible
- Accessible.onPressAction : {
- window.visibility = Window.Minimized
- }
- }
- }
- Rectangle {
- height : root.height
- width : 1.5*height
- color : Style.transparent
- Image {
- id: iconTimes
- anchors.centerIn : parent
- mipmap : true
- height : parent.height/1.5
- fillMode : Image.PreserveAspectFit
- source : "images/win10_Times.png"
- }
- MouseArea {
- anchors.fill : parent
- hoverEnabled : true
- onClicked : window.close()
- onPressed : {
- iconTimes.scale=0.92
- }
- onReleased: {
- parent.scale=1
- }
- onEntered: {
- parent.color=Style.main.textRed
- }
- onExited: {
- parent.color=Style.transparent
- }
-
- Accessible.role : Accessible.Button
- Accessible.name : qsTr("Close", "Close the window button")
- Accessible.description : Accessible.name
- Accessible.ignored : !parent.visible
- Accessible.onPressAction : {
- window.close()
- }
- }
- }
- }
-}
diff --git a/internal/frontend/qml/ProtonUI/qmldir b/internal/frontend/qml/ProtonUI/qmldir
deleted file mode 100644
index ade9e7aa..00000000
--- a/internal/frontend/qml/ProtonUI/qmldir
+++ /dev/null
@@ -1,32 +0,0 @@
-module ProtonUI
-singleton Style 1.0 Style.qml
-AccessibleButton 1.0 AccessibleButton.qml
-AccessibleText 1.0 AccessibleText.qml
-AccessibleSelectableText 1.0 AccessibleSelectableText.qml
-AccountView 1.0 AccountView.qml
-AddAccountBar 1.0 AddAccountBar.qml
-BubbleNote 1.0 BubbleNote.qml
-BugReportWindow 1.0 BugReportWindow.qml
-ButtonIconText 1.0 ButtonIconText.qml
-ButtonRounded 1.0 ButtonRounded.qml
-CheckBoxLabel 1.0 CheckBoxLabel.qml
-ClickIconText 1.0 ClickIconText.qml
-Dialog 1.0 Dialog.qml
-DialogAddUser 1.0 DialogAddUser.qml
-DialogUpdate 1.0 DialogUpdate.qml
-DialogConnectionTroubleshoot 1.0 DialogConnectionTroubleshoot.qml
-FileAndFolderSelect 1.0 FileAndFolderSelect.qml
-InfoToolTip 1.0 InfoToolTip.qml
-InformationBar 1.0 InformationBar.qml
-InputBox 1.0 InputBox.qml
-InputField 1.0 InputField.qml
-InstanceExistsWindow 1.0 InstanceExistsWindow.qml
-LogoHeader 1.0 LogoHeader.qml
-PopupMessage 1.0 PopupMessage.qml
-RoundedRectangle 1.0 RoundedRectangle.qml
-TabButton 1.0 TabButton.qml
-TabLabels 1.0 TabLabels.qml
-TextLabel 1.0 TextLabel.qml
-TextValue 1.0 TextValue.qml
-TLSCertPinIssueBar 1.0 TLSCertPinIssueBar.qml
-WindowTitleBar 1.0 WindowTitleBar.qml
diff --git a/internal/frontend/qml/bridgeqml.qmlproject b/internal/frontend/qml/bridgeqml.qmlproject
new file mode 100644
index 00000000..32007b8c
--- /dev/null
+++ b/internal/frontend/qml/bridgeqml.qmlproject
@@ -0,0 +1,22 @@
+/* File generated by Qt Creator */
+
+import QmlProject 1.1
+
+Project {
+ mainFile: "./MainWindow.qml"
+
+ /* Include .qml, .js, and image files from current directory and subdirectories */
+ QmlFiles {
+ directory: "./"
+ }
+ JavaScriptFiles {
+ directory: "./"
+ }
+ ImageFiles {
+ directory: "./"
+ }
+ /* List of plugin directories passed to QML runtime */
+ importPaths: [
+ "./"
+ ]
+}
diff --git a/internal/frontend/share/icons/Bridge.icns b/internal/frontend/qml/icons/Bridge.icns
similarity index 100%
rename from internal/frontend/share/icons/Bridge.icns
rename to internal/frontend/qml/icons/Bridge.icns
diff --git a/internal/frontend/share/icons/all_icons.svg b/internal/frontend/qml/icons/all_icons.svg
similarity index 100%
rename from internal/frontend/share/icons/all_icons.svg
rename to internal/frontend/qml/icons/all_icons.svg
diff --git a/internal/frontend/share/icons/black-syserror.png b/internal/frontend/qml/icons/black-syserror.png
similarity index 100%
rename from internal/frontend/share/icons/black-syserror.png
rename to internal/frontend/qml/icons/black-syserror.png
diff --git a/internal/frontend/share/icons/black-systray.png b/internal/frontend/qml/icons/black-systray.png
similarity index 100%
rename from internal/frontend/share/icons/black-systray.png
rename to internal/frontend/qml/icons/black-systray.png
diff --git a/internal/frontend/share/icons/black-syswarn.png b/internal/frontend/qml/icons/black-syswarn.png
similarity index 100%
rename from internal/frontend/share/icons/black-syswarn.png
rename to internal/frontend/qml/icons/black-syswarn.png
diff --git a/internal/frontend/share/icons/envelope_open.png b/internal/frontend/qml/icons/envelope_open.png
similarity index 100%
rename from internal/frontend/share/icons/envelope_open.png
rename to internal/frontend/qml/icons/envelope_open.png
diff --git a/internal/frontend/share/icons/export.sh b/internal/frontend/qml/icons/export.sh
similarity index 100%
rename from internal/frontend/share/icons/export.sh
rename to internal/frontend/qml/icons/export.sh
diff --git a/internal/frontend/share/icons/folder_open.png b/internal/frontend/qml/icons/folder_open.png
similarity index 100%
rename from internal/frontend/share/icons/folder_open.png
rename to internal/frontend/qml/icons/folder_open.png
diff --git a/internal/frontend/share/icons/ie.icns b/internal/frontend/qml/icons/ie.icns
similarity index 100%
rename from internal/frontend/share/icons/ie.icns
rename to internal/frontend/qml/icons/ie.icns
diff --git a/internal/frontend/share/icons/ie.ico b/internal/frontend/qml/icons/ie.ico
similarity index 100%
rename from internal/frontend/share/icons/ie.ico
rename to internal/frontend/qml/icons/ie.ico
diff --git a/internal/frontend/share/icons/ie.svg b/internal/frontend/qml/icons/ie.svg
similarity index 100%
rename from internal/frontend/share/icons/ie.svg
rename to internal/frontend/qml/icons/ie.svg
diff --git a/internal/frontend/share/icons/logo.ico b/internal/frontend/qml/icons/logo.ico
similarity index 100%
rename from internal/frontend/share/icons/logo.ico
rename to internal/frontend/qml/icons/logo.ico
diff --git a/internal/frontend/share/icons/logo.svg b/internal/frontend/qml/icons/logo.svg
similarity index 100%
rename from internal/frontend/share/icons/logo.svg
rename to internal/frontend/qml/icons/logo.svg
diff --git a/internal/frontend/share/icons/macos_gray.png b/internal/frontend/qml/icons/macos_gray.png
similarity index 100%
rename from internal/frontend/share/icons/macos_gray.png
rename to internal/frontend/qml/icons/macos_gray.png
diff --git a/internal/frontend/share/icons/macos_green.png b/internal/frontend/qml/icons/macos_green.png
similarity index 100%
rename from internal/frontend/share/icons/macos_green.png
rename to internal/frontend/qml/icons/macos_green.png
diff --git a/internal/frontend/share/icons/macos_green_dark.png b/internal/frontend/qml/icons/macos_green_dark.png
similarity index 100%
rename from internal/frontend/share/icons/macos_green_dark.png
rename to internal/frontend/qml/icons/macos_green_dark.png
diff --git a/internal/frontend/share/icons/macos_green_hl.png b/internal/frontend/qml/icons/macos_green_hl.png
similarity index 100%
rename from internal/frontend/share/icons/macos_green_hl.png
rename to internal/frontend/qml/icons/macos_green_hl.png
diff --git a/internal/frontend/share/icons/macos_red.png b/internal/frontend/qml/icons/macos_red.png
similarity index 100%
rename from internal/frontend/share/icons/macos_red.png
rename to internal/frontend/qml/icons/macos_red.png
diff --git a/internal/frontend/share/icons/macos_red_dark.png b/internal/frontend/qml/icons/macos_red_dark.png
similarity index 100%
rename from internal/frontend/share/icons/macos_red_dark.png
rename to internal/frontend/qml/icons/macos_red_dark.png
diff --git a/internal/frontend/share/icons/macos_red_hl.png b/internal/frontend/qml/icons/macos_red_hl.png
similarity index 100%
rename from internal/frontend/share/icons/macos_red_hl.png
rename to internal/frontend/qml/icons/macos_red_hl.png
diff --git a/internal/frontend/share/icons/macos_yellow.png b/internal/frontend/qml/icons/macos_yellow.png
similarity index 100%
rename from internal/frontend/share/icons/macos_yellow.png
rename to internal/frontend/qml/icons/macos_yellow.png
diff --git a/internal/frontend/share/icons/macos_yellow_dark.png b/internal/frontend/qml/icons/macos_yellow_dark.png
similarity index 100%
rename from internal/frontend/share/icons/macos_yellow_dark.png
rename to internal/frontend/qml/icons/macos_yellow_dark.png
diff --git a/internal/frontend/share/icons/macos_yellow_hl.png b/internal/frontend/qml/icons/macos_yellow_hl.png
similarity index 100%
rename from internal/frontend/share/icons/macos_yellow_hl.png
rename to internal/frontend/qml/icons/macos_yellow_hl.png
diff --git a/internal/frontend/share/icons/pm_logo.png b/internal/frontend/qml/icons/pm_logo.png
similarity index 100%
rename from internal/frontend/share/icons/pm_logo.png
rename to internal/frontend/qml/icons/pm_logo.png
diff --git a/internal/frontend/share/icons/rectangle-app.png b/internal/frontend/qml/icons/rectangle-app.png
similarity index 100%
rename from internal/frontend/share/icons/rectangle-app.png
rename to internal/frontend/qml/icons/rectangle-app.png
diff --git a/internal/frontend/share/icons/rectangle-systray.png b/internal/frontend/qml/icons/rectangle-systray.png
similarity index 100%
rename from internal/frontend/share/icons/rectangle-systray.png
rename to internal/frontend/qml/icons/rectangle-systray.png
diff --git a/internal/frontend/share/icons/rectangle-syswarn.png b/internal/frontend/qml/icons/rectangle-syswarn.png
similarity index 100%
rename from internal/frontend/share/icons/rectangle-syswarn.png
rename to internal/frontend/qml/icons/rectangle-syswarn.png
diff --git a/internal/frontend/share/icons/rounded-app.png b/internal/frontend/qml/icons/rounded-app.png
similarity index 100%
rename from internal/frontend/share/icons/rounded-app.png
rename to internal/frontend/qml/icons/rounded-app.png
diff --git a/internal/frontend/share/icons/rounded-app.svg b/internal/frontend/qml/icons/rounded-app.svg
similarity index 100%
rename from internal/frontend/share/icons/rounded-app.svg
rename to internal/frontend/qml/icons/rounded-app.svg
diff --git a/internal/frontend/share/icons/rounded-systray.png b/internal/frontend/qml/icons/rounded-systray.png
similarity index 100%
rename from internal/frontend/share/icons/rounded-systray.png
rename to internal/frontend/qml/icons/rounded-systray.png
diff --git a/internal/frontend/share/icons/rounded-syswarn.png b/internal/frontend/qml/icons/rounded-syswarn.png
similarity index 100%
rename from internal/frontend/share/icons/rounded-syswarn.png
rename to internal/frontend/qml/icons/rounded-syswarn.png
diff --git a/internal/frontend/share/icons/white-syserror.png b/internal/frontend/qml/icons/white-syserror.png
similarity index 100%
rename from internal/frontend/share/icons/white-syserror.png
rename to internal/frontend/qml/icons/white-syserror.png
diff --git a/internal/frontend/share/icons/white-systray.png b/internal/frontend/qml/icons/white-systray.png
similarity index 100%
rename from internal/frontend/share/icons/white-systray.png
rename to internal/frontend/qml/icons/white-systray.png
diff --git a/internal/frontend/share/icons/white-syswarn.png b/internal/frontend/qml/icons/white-syswarn.png
similarity index 100%
rename from internal/frontend/share/icons/white-syswarn.png
rename to internal/frontend/qml/icons/white-syswarn.png
diff --git a/internal/frontend/share/icons/win10_Dash.png b/internal/frontend/qml/icons/win10_Dash.png
similarity index 100%
rename from internal/frontend/share/icons/win10_Dash.png
rename to internal/frontend/qml/icons/win10_Dash.png
diff --git a/internal/frontend/share/icons/win10_Times.png b/internal/frontend/qml/icons/win10_Times.png
similarity index 100%
rename from internal/frontend/share/icons/win10_Times.png
rename to internal/frontend/qml/icons/win10_Times.png
diff --git a/internal/frontend/qml/tst_Gui.qml b/internal/frontend/qml/tst_Gui.qml
deleted file mode 100644
index 6ab0c799..00000000
--- a/internal/frontend/qml/tst_Gui.qml
+++ /dev/null
@@ -1,651 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-import QtQuick 2.8
-import QtTest 1.2
-import BridgeUI 1.0
-import ProtonUI 1.0
-import QtQuick.Controls 2.1
-import QtQuick.Window 2.2
-
-Window {
- id: testroot
- width : 250
- height : 600
- flags : Qt.Window | Qt.Dialog | Qt.FramelessWindowHint
- visible : true
- title : "GUI test Window"
- color : "transparent"
-
- property bool newVersion : true
-
- Accessible.name: testroot.title
- Accessible.description: "Window with buttons testing the GUI events"
-
-
- Rectangle {
- id:test_systray
- anchors{
- top: parent.top
- horizontalCenter: parent.horizontalCenter
- }
- height: 40
- width: testroot.width
- color: "yellow"
- Image {
- id: sysImg
- anchors {
- left : test_systray.left
- top : test_systray.top
- }
- height: test_systray.height
- mipmap: true
- fillMode : Image.PreserveAspectFit
- source: ""
- }
- Text {
- id: systrText
- anchors {
- horizontalCenter: parent.horizontalCenter
- verticalCenter: test_systray.verticalCenter
- }
- text: "unset"
- }
-
- function normal() {
- test_systray.color = "#22ee22"
- systrText.text = "norm"
- sysImg.source= "../share/icons/black-systray.png"
- }
- function highlight() {
- test_systray.color = "#eeee22"
- systrText.text = "highl"
- sysImg.source= "../share/icons/black-syswarn.png"
- }
- function error() {
- test_systray.color = "#ee2222"
- systrText.text = "error"
- sysImg.source= "../share/icons/black-syserror.png"
- }
-
- MouseArea {
- property point diff: "0,0"
- anchors.fill: parent
- onPressed: {
- diff = Qt.point(testroot.x, testroot.y)
- var mousePos = mapToGlobal(mouse.x, mouse.y)
- diff.x -= mousePos.x
- diff.y -= mousePos.y
- }
- onPositionChanged: {
- var currPos = mapToGlobal(mouse.x, mouse.y)
- testroot.x = currPos.x + diff.x
- testroot.y = currPos.y + diff.y
- }
- }
- }
-
- ListModel {
- id: buttons
-
- ListElement { title: "Show window" }
- ListElement { title: "Show help" }
- ListElement { title: "Show quit" }
- ListElement { title: "Logout bridge" }
- ListElement { title: "Internet on" }
- ListElement { title: "Internet off" }
- ListElement { title: "UpToDate" }
- ListElement { title: "NotifyManualUpdate(CanInstall)" }
- ListElement { title: "NotifyManualUpdate(CantInstall)" }
- ListElement { title: "NotifyManualUpdateRestart" }
- ListElement { title: "NotifyManualUpdateError" }
- ListElement { title: "ForceUpdate" }
- ListElement { title: "NotifySilentUpdateRestartNeeded" }
- ListElement { title: "NotifySilentUpdateError" }
- ListElement { title: "Linux" }
- ListElement { title: "Windows" }
- ListElement { title: "Macos" }
- ListElement { title: "FirstDialog" }
- ListElement { title: "AutostartError" }
- ListElement { title: "BusyPortIMAP" }
- ListElement { title: "BusyPortSMTP" }
- ListElement { title: "BusyPortBOTH" }
- ListElement { title: "Minimize this" }
- ListElement { title: "SendAlertPopup" }
- ListElement { title: "TLSCertError" }
- }
-
- ListView {
- id: view
- anchors {
- top : test_systray.bottom
- bottom : parent.bottom
- left : parent.left
- right : parent.right
- }
-
- orientation : ListView.Vertical
- model : buttons
- focus : true
-
- delegate : ButtonRounded {
- text : title
- color_main : "orange"
- color_minor : "#aa335588"
- isOpaque : true
- width: testroot.width
- height : 20*Style.px
- anchors.horizontalCenter: parent.horizontalCenter
- onClicked : {
- console.log("Clicked on ", title)
- switch (title) {
- case "Show window" :
- go.showWindow();
- break;
- case "Show help" :
- go.showHelp();
- break;
- case "Show quit" :
- go.showQuit();
- break;
- case "Logout bridge" :
- go.checkLoggedOut("bridge");
- break;
- case "Internet on" :
- go.setConnectionStatus(true);
- break;
- case "Internet off" :
- go.setConnectionStatus(false);
- break;
- case "Linux" :
- go.goos = "linux";
- break;
- case "Macos" :
- go.goos = "darwin";
- break;
- case "Windows" :
- go.goos = "windows";
- break;
- case "FirstDialog" :
- testgui.winMain.dialogFirstStart.show();
- break;
- case "AutostartError" :
- go.notifyBubble(1,go.failedAutostart);
- break;
- case "BusyPortIMAP" :
- go.notifyPortIssue(true,false);
- break;
- case "BusyPortSMTP" :
- go.notifyPortIssue(false,true);
- break;
- case "BusyPortBOTH" :
- go.notifyPortIssue(true,true);
- break;
- case "Minimize this" :
- testroot.visibility = Window.Minimized
- break;
- case "UpToDate" :
- testroot.newVersion = false
- break;
- case "NotifyManualUpdate(CanInstall)" :
- go.notifyManualUpdate()
- go.updateCanInstall = true
- break;
- case "NotifyManualUpdate(CantInstall)" :
- go.notifyManualUpdate()
- go.updateCanInstall = false
- break;
- case "NotifyManualUpdateRestart":
- go.notifyManualUpdateRestartNeeded()
- break;
- case "NotifyManualUpdateError":
- go.notifyManualUpdateError()
- break;
- case "ForceUpdate" :
- go.notifyForceUpdate()
- break;
- case "NotifySilentUpdateRestartNeeded" :
- go.notifySilentUpdateRestartNeeded()
- break;
- case "NotifySilentUpdateError" :
- go.notifySilentUpdateError()
- break;
- case "SendAlertPopup" :
- go.showOutgoingNoEncPopup("Alert sending unencrypted!")
- break;
- case "TLSCertError" :
- go.showCertIssue()
- break;
- default :
- console.log("Not implemented " + data)
- }
- }
- }
- }
-
-
- Component.onCompleted : {
- testroot.x= 10
- testroot.y= 100
- }
-
- //InstanceExistsWindow { id: ie_test }
-
- Gui {
- id: testgui
-
- ListModel{
- id: accountsModel
- ListElement{ account : "bridge" ; status : "connected"; isExpanded: false; isCombinedAddressMode: false; hostname : "127.0.0.1"; password : "ZI9tKp+ryaxmbpn2E12"; security : "StarTLS"; portSMTP : 1025; portIMAP : 1143; aliases : "bridge@pm.com;bridge2@pm.com;theHorriblySlowMurderWithExtremelyInefficientWeapon@youtube.com" }
- ListElement{ account : "exteremelongnamewhichmustbeeladed@protonmail.com" ; status : "connected"; isExpanded: true; isCombinedAddressMode: true; hostname : "127.0.0.1"; password : "ZI9tKp+ryaxmbpn2E12"; security : "StarTLS"; portSMTP : 1025; portIMAP : 1143; aliases : "bridge@pm.com;bridge2@pm.com;hu@hu.hu" }
- ListElement{ account : "bridge2@protonmail.com" ; status : "disconnected"; isExpanded: false; isCombinedAddressMode: false; hostname : "127.0.0.1"; password : "ZI9tKp+ryaxmbpn2E12"; security : "StarTLS"; portSMTP : 1025; portIMAP : 1143; aliases : "bridge@pm.com;bridge2@pm.com;hu@hu.hu" }
- }
-
- Component.onCompleted : {
- winMain.x = testroot.x + testroot.width
- winMain.y = testroot.y
- }
- }
-
-
- QtObject {
- id: go
-
- property bool isAutoStart : true
- property bool isAutoUpdate : false
- property bool isEarlyAccess : false
- property bool isProxyAllowed : false
- property bool isFirstStart : false
- property bool isFreshVersion : false
- property bool isOutdateVersion : true
- property string currentAddress : "none"
- //property string goos : "windows"
- property string goos : "linux"
- ////property string goos : "darwin"
- property bool isDefaultPort : false
- property bool isShownOnStart : true
-
- property bool hasNoKeychain : true
-
- property var availableKeychain: ["pass-app", "gnome-keyring"]
- property var selectedKeychain: "gnome-keyring"
-
- property string wrongCredentials
- property string wrongMailboxPassword
- property string canNotReachAPI
- property string versionCheckFailed
- property string credentialsNotRemoved
- property string bugNotSent
- property string bugReportSent
- property string failedAutostartPerm
- property string failedAutostart
- property string genericErrSeeLogs
-
- property string programTitle : "ProtonMail Bridge"
- property string fullversion : "QA.1.0 (d9f8sdf9) 2020-02-19T10:57:23+01:00"
- property string downloadLink: "https://protonmail.com/download/beta/protonmail-bridge-1.1.5-1.x86_64.rpm;https://www.protonmail.com/downloads/beta/Desktop-Bridge-link1.exe;https://www.protonmail.com/downloads/beta/Desktop-Bridge-link1.exe;https://www.protonmail.com/downloads/beta/Desktop-Bridge-link1.exe;"
-
- property string updateState
- property string updateVersion : "QA.1.0"
- property bool updateCanInstall: true
- property string updateLandingPage : "https://protonmail.com/bridge/download/"
- property string updateReleaseNotesLink : "" // "https://protonmail.com/download/bridge/release_notes.html"
- signal notifyManualUpdate()
- signal notifyManualUpdateRestartNeeded()
- signal notifyManualUpdateError()
- signal notifyForceUpdate()
- signal notifySilentUpdateRestartNeeded()
- signal notifySilentUpdateError()
- function checkForUpdates() {
- console.log("checkForUpdates")
- go.notifyVersionIsTheLatest()
- }
- function startManualUpdate() {
- console.log("startManualUpdate")
- }
- function checkAndOpenReleaseNotes() {
- console.log("check for release notes")
- go.updateReleaseNotesLink = "https://protonmail.com/download/bridge/release_notes.html"
- go.openReleaseNotesExternally()
- }
-
-
- property string credits : "here;goes;list;;of;;used;packages;"
-
- property real progress: 0.3
- property int progressDescription: 2
-
- function setToRestart() {
- console.log("setting to restart")
- }
-
- signal toggleMainWin(int systX, int systY, int systW, int systH)
-
- signal showWindow()
- signal showHelp()
- signal showQuit()
-
- signal notifyPortIssue(bool busyPortIMAP, bool busyPortSMTP)
- signal notifyVersionIsTheLatest()
- signal notifyKeychainRebuild()
- signal notifyHasNoKeychain()
-
- signal processFinished()
- signal toggleAutoStart()
- signal toggleEarlyAccess()
- signal toggleAutoUpdate()
- signal notifyBubble(int tabIndex, string message)
- signal silentBubble(int tabIndex, string message)
- signal setAddAccountWarning(string message)
-
- signal notifyFirewall()
- signal notifyLogout(string accname)
- signal notifyAddressChanged(string accname)
- signal notifyAddressChangedLogout(string accname)
- signal failedAutostartCode(string code)
-
- signal openReleaseNotesExternally()
- signal showCertIssue()
-
- signal updateFinished(bool hasError)
-
- signal guiIsReady()
-
- signal showOutgoingNoEncPopup(string subject)
- signal setOutgoingNoEncPopupCoord(real x, real y)
- signal showNoActiveKeyForRecipient(string recipient)
-
- function delay(duration) {
- var timeStart = new Date().getTime();
-
- while (new Date().getTime() - timeStart < duration) {
- // Do nothing
- }
- }
-
- function getLastMailClient() {
- return "Mutt is the best"
- }
-
- function sendBug(desc,client,address){
- console.log("bug report ", "desc '"+desc+"'", "client '"+client+"'", "address '"+address+"'")
- return !desc.includes("fail")
- }
-
- function deleteAccount(index,remove) {
- console.log ("Test: Delete account ",index," and remove prefences "+remove)
- workAndClose()
- accountsModel.remove(index)
- }
-
- function logoutAccount(index) {
- accountsModel.get(index).status="disconnected"
- workAndClose()
- }
-
- function login(username,password) {
- delay(700)
- if (password=="wrong") {
- setAddAccountWarning("Wrong password")
- return -1
- }
- if (username=="2fa") {
- return 1
- }
- if (username=="mbox") {
- return 2
- }
- return 0
- }
-
- function auth2FA(twoFACode){
- delay(700)
- if (twoFACode=="wrong") {
- setAddAccountWarning("Wrong 2FA")
- return -1
- }
- if (twoFACode=="mbox") {
- return 1
- }
- return 0
- }
-
- function addAccount(mailboxPass) {
- delay(700)
- if (mailboxPass=="wrong") {
- setAddAccountWarning("Wrong mailbox password")
- return -1
- }
- accountsModel.append({
- "account" : testgui.winMain.dialogAddUser.username,
- "status" : "connected",
- "isExpanded":true,
- "hostname" : "127.0.0.1",
- "password" : "ZI9tKp+ryaxmbpn2E12",
- "security" : "StarTLS",
- "portSMTP" : 1025,
- "portIMAP" : 1143,
- "aliases" : "bridge@pm.com;bridges@pm.com;theHorriblySlowMurderWithExtremelyInefficientWeapon@youtube.com",
- "isCombinedAddressMode": true
- })
- workAndClose()
- }
-
- function checkInternet() {
- var delay = Qt.createQmlObject("import QtQuick 2.8; Timer{}",go)
- delay.interval = 2000
- delay.repeat = false
- delay.triggered.connect(function(){ go.setConnectionStatus(false) })
- delay.start()
- }
-
- property SequentialAnimation animateProgressBar : SequentialAnimation {
- // version
- PropertyAnimation{ target: go; properties: "progressDescription"; to: 1; duration: 1; }
- PropertyAnimation{ duration: 2000; }
-
- // download
- PropertyAnimation{ target: go; properties: "progressDescription"; to: 2; duration: 1; }
- PropertyAnimation{ duration: 500; }
- PropertyAnimation{ target: go; properties: "progress"; to: 0.01; duration: 1; }
- PropertyAnimation{ duration: 500; }
- PropertyAnimation{ target: go; properties: "progress"; to: 0.1; duration: 1; }
- PropertyAnimation{ duration: 500; }
- PropertyAnimation{ target: go; properties: "progress"; to: 0.3; duration: 1; }
- PropertyAnimation{ duration: 500; }
- PropertyAnimation{ target: go; properties: "progress"; to: 0.5; duration: 1; }
- PropertyAnimation{ duration: 500; }
- PropertyAnimation{ target: go; properties: "progress"; to: 0.8; duration: 1; }
- PropertyAnimation{ duration: 500; }
- PropertyAnimation{ target: go; properties: "progress"; to: 1.0; duration: 1; }
- PropertyAnimation{ duration: 1000; }
-
- // verify
- PropertyAnimation{ target: go; properties: "progress"; to: 0.0; duration: 1; }
- PropertyAnimation{ target: go; properties: "progressDescription"; to: 3; duration: 1; }
- PropertyAnimation{ duration: 2000; }
-
- // unzip
- PropertyAnimation{ target: go; properties: "progressDescription"; to: 4; duration: 1; }
- PropertyAnimation{ duration: 500; }
- PropertyAnimation{ target: go; properties: "progress"; to: 0.01; duration: 1; }
- PropertyAnimation{ duration: 500; }
- PropertyAnimation{ target: go; properties: "progress"; to: 0.1; duration: 1; }
- PropertyAnimation{ duration: 500; }
- PropertyAnimation{ target: go; properties: "progress"; to: 0.3; duration: 1; }
- PropertyAnimation{ duration: 500; }
- PropertyAnimation{ target: go; properties: "progress"; to: 0.5; duration: 1; }
- PropertyAnimation{ duration: 500; }
- PropertyAnimation{ target: go; properties: "progress"; to: 0.8; duration: 1; }
- PropertyAnimation{ duration: 500; }
- PropertyAnimation{ target: go; properties: "progress"; to: 1.0; duration: 1; }
- PropertyAnimation{ duration: 2000; }
-
- // update
- PropertyAnimation{ target: go; properties: "progress"; to: 0.0; duration: 1; }
- PropertyAnimation{ target: go; properties: "progressDescription"; to: 5; duration: 1; }
- PropertyAnimation{ duration: 2000; }
-
- // quit
- PropertyAnimation{ target: go; properties: "progressDescription"; to: 6; duration: 1; }
- PropertyAnimation{ duration: 2000; }
-
- }
-
- property Timer timer : Timer {
- id: timer
- interval : 700
- repeat : false
- property string work
- onTriggered : {
- console.log("triggered "+timer.work)
- switch (timer.work) {
- case "wait":
- break
- default:
- go.processFinished()
- }
- }
- }
- function workAndClose() {
- timer.work="default"
- timer.start()
- }
-
- function loadAccounts() {
- console.log("Test: Account loaded")
- }
-
-
- function openDownloadLink(){
- }
-
- function switchAddressMode(username){
- for (var iAcc=0; iAcc < accountsModel.count; iAcc++) {
- if (accountsModel.get(iAcc).account == username ) {
- accountsModel.get(iAcc).isCombinedAddressMode = !accountsModel.get(iAcc).isCombinedAddressMode
- break
- }
- }
- workAndClose()
- }
-
- function getLocalVersionInfo(){
- go.updateVersion = "QA.1.0"
- }
-
- function getBackendVersion() {
- return "BridgeUI 1.0"
- }
-
- property bool isConnectionOK : true
- signal setConnectionStatus(bool isAvailable)
-
- function configureAppleMail(iAccount,iAddress) {
- console.log ("Test: autoconfig account ",iAccount," address ",iAddress)
- }
-
- function openLogs() {
- Qt.openUrlExternally("file:///home/dev/")
- }
-
- function highlightSystray() {
- test_systray.highlight()
- }
-
- function errorSystray() {
- test_systray.error()
- }
-
- function normalSystray() {
- test_systray.normal()
- }
-
- signal bubbleClosed()
-
- function getIMAPPort() {
- return 1143
- }
- function getSMTPPort() {
- return 1025
- }
-
- function isPortOpen(portstring){
- if (isNaN(portstring)) {
- return 1
- }
- var portnum = parseInt(portstring,10)
- if (portnum < 3333) {
- return 1
- }
- return 0
- }
-
- function setPortsAndSecurity(portIMAP, portSMTP, secSMTP) {
- console.log("Test: ports changed", portIMAP, portSMTP, secSMTP)
- }
-
- function isSMTPSTARTTLS() {
- return true
- }
-
- signal openManual()
-
- function clearCache() {
- workAndClose()
- }
-
- function clearKeychain() {
- workAndClose()
- }
-
- property bool isReportingOutgoingNoEnc : true
-
- function toggleIsReportingOutgoingNoEnc() {
- go.isReportingOutgoingNoEnc = !go.isReportingOutgoingNoEnc
- console.log("Reporting changed to ", go.isReportingOutgoingNoEnc)
- }
-
- function saveOutgoingNoEncPopupCoord(x,y) {
- console.log("Triggered saveOutgoingNoEncPopupCoord: ",x,y)
- }
-
- function shouldSendAnswer (messageID, shouldSend) {
- if (shouldSend) console.log("answered to send email")
- else console.log("answered to cancel email")
- }
-
- onToggleAutoStart: {
- workAndClose()
- isAutoStart = (isAutoStart!=false) ? false : true
- console.log (" Test: toggleAutoStart "+isAutoStart)
- }
-
- onToggleAutoUpdate: {
- workAndClose()
- isAutoUpdate = (isAutoUpdate!=false) ? false : true
- console.log (" Test: onToggleAutoUpdate "+isAutoUpdate)
- }
-
- onToggleEarlyAccess: {
- workAndClose()
- isEarlyAccess = (isEarlyAccess!=false) ? false : true
- console.log (" Test: onToggleEarlyAccess "+isEarlyAccess)
- }
- }
-}
-
diff --git a/internal/frontend/qml/tst_GuiIE.qml b/internal/frontend/qml/tst_GuiIE.qml
deleted file mode 100644
index cd58ae84..00000000
--- a/internal/frontend/qml/tst_GuiIE.qml
+++ /dev/null
@@ -1,1360 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-import QtQuick 2.8
-import ImportExportUI 1.0
-import ProtonUI 1.0
-import QtQuick.Controls 2.1
-import QtQuick.Window 2.2
-
-Window {
- id : testroot
- width : 150
- height : 600
- flags : Qt.Window | Qt.Dialog | Qt.FramelessWindowHint
- visible : true
- title : "GUI test Window"
- color : "transparent"
- x : testgui.winMain.x - 170
- y : testgui.winMain.y
-
- property bool newVersion : true
-
- Accessible.name: testroot.title
- Accessible.description: "Window with buttons testing the GUI events"
-
-
- Rectangle {
- id:test_systray
- anchors{
- top: parent.top
- horizontalCenter: parent.horizontalCenter
- }
- height: 40
- width: 100
- color: "yellow"
- Image {
- id: sysImg
- anchors {
- left : test_systray.left
- top : test_systray.top
- }
- height: test_systray.height
- mipmap: true
- fillMode : Image.PreserveAspectFit
- source: ""
- }
- Text {
- id: systrText
- anchors {
- right : test_systray.right
- verticalCenter: test_systray.verticalCenter
- }
- text: "unset"
- }
-
- function normal() {
- test_systray.color = "#22ee22"
- systrText.text = "norm"
- sysImg.source= "../share/icons/rounded-systray.png"
- }
- function highlight() {
- test_systray.color = "#eeee22"
- systrText.text = "highl"
- sysImg.source= "../share/icons/rounded-syswarn.png"
- }
-
- MouseArea {
- property point diff: "0,0"
- anchors.fill: parent
- onPressed: {
- diff = Qt.point(testroot.x, testroot.y)
- var mousePos = mapToGlobal(mouse.x, mouse.y)
- diff.x -= mousePos.x
- diff.y -= mousePos.y
- }
- onPositionChanged: {
- var currPos = mapToGlobal(mouse.x, mouse.y)
- testroot.x = currPos.x + diff.x
- testroot.y = currPos.y + diff.y
- }
- }
- }
-
- ListModel {
- id: buttons
-
- ListElement { title : "Show window" }
- ListElement { title : "Logout" }
- ListElement { title : "Internet on" }
- ListElement { title : "Internet off" }
- ListElement { title : "Macos" }
- ListElement { title : "Windows" }
- ListElement { title : "Linux" }
- ListElement { title: "NotifyManualUpdate(CanInstall)" }
- ListElement { title: "NotifyManualUpdate(CantInstall)" }
- ListElement { title: "NotifyManualUpdateRestart" }
- ListElement { title: "NotifyManualUpdateError" }
- ListElement { title: "ForceUpdate" }
- //ListElement { title: "NotifySilentUpdateRestartNeeded" }
- //ListElement { title: "NotifySilentUpdateError" }
- ListElement { title : "ImportStructure" }
- ListElement { title : "DraftImpFailed" }
- ListElement { title : "NoInterImp" }
- ListElement { title : "ReportImp" }
- ListElement { title : "NewFolder" }
- ListElement { title : "EditFolder" }
- ListElement { title : "EditLabel" }
- ListElement { title : "ExpProgErr" }
- ListElement { title : "ImpProgErr" }
- }
-
- ListView {
- id: view
- anchors {
- top : test_systray.bottom
- bottom : parent.bottom
- left : parent.left
- right : parent.right
- }
-
- orientation : ListView.Vertical
- model : buttons
- focus : true
-
- delegate : ButtonRounded {
- text : title
- color_main : "orange"
- color_minor : "#aa335588"
- isOpaque : true
- anchors.horizontalCenter: parent.horizontalCenter
- onClicked : {
- console.log("Clicked on ", title)
- switch (title) {
- case "Show window" :
- go.showWindow();
- break;
- case "Logout" :
- go.checkLoggedOut("ie");
- break;
- case "Internet on" :
- go.setConnectionStatus(true);
- break;
- case "Internet off" :
- go.setConnectionStatus(false);
- break;
- case "Macos" :
- go.goos = "darwin";
- break;
- case "Windows" :
- go.goos = "windows";
- break;
- case "Linux" :
- go.goos = "linux";
- break;
- case "NotifyManualUpdate(CanInstall)" :
- go.notifyManualUpdate()
- go.updateCanInstall = true
- break;
- case "NotifyManualUpdate(CantInstall)" :
- go.notifyManualUpdate()
- go.updateCanInstall = false
- break;
- case "NotifyManualUpdateRestart":
- go.notifyManualUpdateRestartNeeded()
- break;
- case "NotifyManualUpdateError":
- go.notifyManualUpdateError()
- break;
- case "ForceUpdate" :
- go.notifyForceUpdate()
- break;
- //case "NotifySilentUpdateRestartNeeded" :
- //go.notifySilentUpdateRestartNeeded()
- //break;
- //case "NotifySilentUpdateError" :
- //go.notifySilentUpdateError()
- //break;
- case "ImportStructure" :
- testgui.winMain.dialogImport.address = "cuto@pm.com"
- testgui.winMain.dialogImport.show()
- testgui.winMain.dialogImport.currentIndex=DialogImport.Page.SourceToTarget
- break
- case "DraftImpFailed" :
- testgui.notifyError(testgui.enums.errDraftImportFailed)
- break
- case "NoInterImp" :
- testgui.notifyError(testgui.enums.errNoInternetWhileImport)
- break
- case "ReportImp" :
- testgui.winMain.dialogImport.address = "cuto@pm.com"
- testgui.winMain.dialogImport.show()
- testgui.winMain.dialogImport.currentIndex=DialogImport.Page.Report
- break
- case "NewFolder" :
- testgui.winMain.popupFolderEdit.show("currentName", "", "", testgui.enums.folderTypeFolder, "")
- break
- case "EditFolder" :
- testgui.winMain.popupFolderEdit.show("currentName", "", "#7272a7", testgui.enums.folderTypeFolder, "")
- break
- case "EditFolder" :
- testgui.winMain.popupFolderEdit.show("currentName", "", "", testgui.enums.folderTypeFolder, "")
- break
- case "ImpProgErr" :
- go.animateProgressBar.pause()
- testgui.notifyError(testgui.enums.errEmailImportFailed)
- break
- case "ExpProgErr" :
- go.animateProgressBar.pause()
- testgui.notifyError(testgui.enums.errEmailExportFailed)
- break
- default :
- console.log("Not implemented " + title)
- }
- }
- }
- }
-
-
- Component.onCompleted : {
- testgui.winMain.x = 350
- testgui.winMain.y = 100
- }
-
- //InstanceExistsWindow { id: ie_test }
-
- GuiIE {
- id: testgui
- //checkLogTimer.interval: 3*1000
- winMain.visible: true
-
- ListModel{
- id: accountsModel
- ListElement{ account : "ie" ; status : "connected"; isExpanded: false; isCombinedAddressMode: false; hostname : "127.0.0.1"; password : "ZI9tKp+ryaxmbpn2E12"; security : "StarTLS"; portSMTP : 1025; portIMAP : 1143; aliases : "ie@pm.com;jaku@pm.com;DoYouKnowAboutAMovieCalledTheHorriblySlowMurderWithExtremelyInefficientWeapon@thatYouCanFindForExampleOnyoutube.com" }
- ListElement{ account : "exteremelongnamewhichmustbeeladedinthemiddleoftheaddress@protonmail.com" ; status : "connected"; isExpanded: true; isCombinedAddressMode: true; hostname : "127.0.0.1"; password : "ZI9tKp+ryaxmbpn2E12"; security : "StarTLS"; portSMTP : 1025; portIMAP : 1143; aliases : "ie@pm.com;jaku@pm.com;hu@hu.hu" }
- ListElement{ account : "ie2@protonmail.com" ; status : "disconnected"; isExpanded: false; isCombinedAddressMode: false; hostname : "127.0.0.1"; password : "ZI9tKp+ryaxmbpn2E12"; security : "StarTLS"; portSMTP : 1025; portIMAP : 1143; aliases : "ie@pm.com;jaku@pm.com;hu@hu.hu" }
- ListElement{ account : "many@protonmail.com" ; status : "connected"; isExpanded: true; isCombinedAddressMode: true; hostname : "127.0.0.1"; password : "ZI9tKp+ryaxmbpn2E12"; security : "StarTLS"; portSMTP : 1025; portIMAP : 1143; aliases : "ie@pm.com;jaku@pm.com;hu@hu.hu;ie@pm.com;jaku@pm.com;hu@hu.hu;ie@pm.com;jaku@pm.com;hu@hu.hu;ie@pm.com;jaku@pm.com;hu@hu.hu;ie@pm.com;jaku@pm.com;hu@hu.hu;ie@pm.com;jaku@pm.com;hu@hu.hu;ie@pm.com;jaku@pm.com;hu@hu.hu;ie@pm.com;jaku@pm.com;hu@hu.hu;ie@pm.com;jaku@pm.com;hu@hu.hu;ie@pm.com;jaku@pm.com;hu@hu.hu;ie@pm.com;jaku@pm.com;hu@hu.hu;ie@pm.com;jaku@pm.com;hu@hu.hu;ie@pm.com;jaku@pm.com;hu@hu.hu;ie@pm.com;jaku@pm.com;hu@hu.hu;ie@pm.com;jaku@pm.com;hu@hu.hu;"}
- }
-
- ListModel{
- id: structureExternalOFF
-
- property var globalOptions: JSON.parse('{ "folderId" : "global--uniq" , "folderName" : "" , "folderColor" : "" , "folderType" : "" , "folderEntries" : 0, "fromDate": 0, "toDate": 0, "isFolderSelected" : false , "targetFolderID": "14" , "targetLabelIDs": ";20;29" }')
-
- ListElement{ folderId : "Inbox" ; folderName : "Inbox" ; folderColor : "black" ; folderType : "" ; folderEntries : 1 ; fromDate : 0 ; toDate : 0 ; isFolderSelected : true ; targetFolderID : "14" ; targetLabelIDs : ";20;29" }
- ListElement{ folderId : "Sent" ; folderName : "Sent" ; folderColor : "black" ; folderType : "" ; folderEntries : 2 ; fromDate : 0 ; toDate : 0 ; isFolderSelected : false ; targetFolderID : "" ; targetLabelIDs : "" }
- ListElement{ folderId : "Spam" ; folderName : "Spam" ; folderColor : "black" ; folderType : "" ; folderEntries : 3 ; fromDate : 0 ; toDate : 0 ; isFolderSelected : false ; targetFolderID : "" ; targetLabelIDs : "" }
- ListElement{ folderId : "Draft" ; folderName : "Draft" ; folderColor : "black" ; folderType : "" ; folderEntries : 4 ; fromDate : 0 ; toDate : 0 ; isFolderSelected : true ; targetFolderID : "14" ; targetLabelIDs : ";20;29" }
-
- ListElement{ folderId : "Folder0" ; folderName : "Folder0" ; folderColor : "black" ; folderType : "folder" ; folderEntries : 10 ; fromDate : 300000 ; toDate : 15000000 ; isFolderSelected : true ; targetFolderID : "14" ; targetLabelIDs : ";20;29" }
- ListElement{ folderId : "Folder1" ; folderName : "Folder1" ; folderColor : "black" ; folderType : "folder" ; folderEntries : 20 ; fromDate : 300000 ; toDate : 15000000 ; isFolderSelected : false ; targetFolderID : "" ; targetLabelIDs : "" }
- ListElement{ folderId : "Folder2" ; folderName : "Folder2" ; folderColor : "black" ; folderType : "folder" ; folderEntries : 30 ; fromDate : 300000 ; toDate : 15000000 ; isFolderSelected : true ; targetFolderID : "14" ; targetLabelIDs : ";20;29" }
- ListElement{ folderId : "Folder3" ; folderName : "Folder3ToolongAndMustBeElidedSimilarToOnOfAccountsItJustNotNeedToBeThatLong" ; folderColor : "black" ; folderType : "folder" ; folderEntries : 40 ; fromDate : 300000 ; toDate : 15000000 ; isFolderSelected : false ; targetFolderID : "" ; targetLabelIDs : "" }
-
- ListElement{ folderId : "Label0" ; folderName : "Label-" ; folderColor : "black" ; folderType : "label" ; folderEntries : 10 ; fromDate : 300000 ; toDate : 15000000 ; isFolderSelected : false ; targetFolderID : "" ; targetLabelIDs : "" }
- ListElement{ folderId : "Label1" ; folderName : "Label1" ; folderColor : "black" ; folderType : "label" ; folderEntries : 11 ; fromDate : 300000 ; toDate : 15000000 ; isFolderSelected : true ; targetFolderID : "14" ; targetLabelIDs : ";20;29" }
- ListElement{ folderId : "Label2" ; folderName : "Label2" ; folderColor : "black" ; folderType : "label" ; folderEntries : 12 ; fromDate : 300000 ; toDate : 15000000 ; isFolderSelected : false ; targetFolderID : "" ; targetLabelIDs : "" }
- ListElement{ folderId : "Label3" ; folderName : "Label3" ; folderColor : "black" ; folderType : "label" ; folderEntries : 13 ; fromDate : 300000 ; toDate : 15000000 ; isFolderSelected : true ; targetFolderID : "14" ; targetLabelIDs : ";20;29" }
-
- function addTargetLabelID ( id , label ) { structureFuncs.addTargetLabelID ( structureExternal , id , label ) }
- function removeTargetLabelID ( id , label ) { structureFuncs.removeTargetLabelID ( structureExternal , id , label ) }
- function setTargetFolderID ( id , label ) { structureFuncs.setTargetFolderID ( structureExternal , id , label ) }
- function setFromToDate ( id , from, to ) { structureFuncs.setFromToDate ( structureExternal , id , from, to ) }
-
- function getID ( row ) { return row == -1 ? structureExternal.globalOptions.folderId : structureExternal.get(row).folderId }
- function getById ( folderId ) { return structureFuncs.getById ( structureExternal , folderId ) }
- function getFrom ( folderId ) { return structureExternal.getById ( folderId ) .fromDate }
- function getTo ( folderId ) { return structureExternal.getById ( folderId ) .toDate }
- function getTargetLabelIDs ( folderId ) { return structureExternal.getById ( folderId ) .getTargetLabelIDs }
- function hasFolderWithName ( folderName ) { return structureFuncs.hasFolderWithName ( structureExternal , folderName ) }
-
- function hasTarget () { return structureFuncs.hasTarget(structureExternal) }
- }
-
- ListModel{
- id: structurePMOFF
-
- // group selectors
- property bool selectedLabels : false
- property bool selectedFolders : false
- property bool atLeastOneSelected : true
-
- property var globalOptions: JSON.parse('{ "folderId" : "global--uniq" , "folderName" : "global" , "folderColor" : "black" , "folderType" : "" , "folderEntries" : 0 , "fromDate": 300000 , "toDate": 15000000 , "isFolderSelected" : false , "targetFolderID": "14" , "targetLabelIDs": ";20;29" }')
-
- ListElement{ folderId : "0" ; folderName : "INBOX" ; folderColor : "blue" ; folderType : "" ; folderEntries : 1 ; isFolderSelected : true ; targetFolderID : "" ; targetLabelIDs : "" ; }
- ListElement{ folderId : "1" ; folderName : "Sent" ; folderColor : "blue" ; folderType : "" ; folderEntries : 2 ; isFolderSelected : false ; targetFolderID : "" ; targetLabelIDs : "" ; }
- ListElement{ folderId : "2" ; folderName : "Spam" ; folderColor : "blue" ; folderType : "" ; folderEntries : 3 ; isFolderSelected : false ; targetFolderID : "" ; targetLabelIDs : "" ; }
- ListElement{ folderId : "3" ; folderName : "Draft" ; folderColor : "blue" ; folderType : "" ; folderEntries : 4 ; isFolderSelected : true ; targetFolderID : "" ; targetLabelIDs : "" ; }
- ListElement{ folderId : "6" ; folderName : "Archive" ; folderColor : "blue" ; folderType : "" ; folderEntries : 5 ; isFolderSelected : true ; targetFolderID : "" ; targetLabelIDs : "" ; }
-
- ListElement{ folderId : "14" ; folderName : "Folder0" ; folderColor : "blue" ; folderType : "folder" ; folderEntries : 10 ; isFolderSelected : true ; targetFolderID : "" ; targetLabelIDs : "" ; }
- ListElement{ folderId : "15" ; folderName : "Folder1" ; folderColor : "green" ; folderType : "folder" ; folderEntries : 20 ; isFolderSelected : false ; targetFolderID : "" ; targetLabelIDs : "" ; }
- ListElement{ folderId : "16" ; folderName : "Folder2" ; folderColor : "pink" ; folderType : "folder" ; folderEntries : 30 ; isFolderSelected : true ; targetFolderID : "" ; targetLabelIDs : "" ; }
- ListElement{ folderId : "17" ; folderName : "Folder3ToolongAndMustBeElidedSimilarToOnOfAccountsItJustNotNeedToBeThatLong" ; folderColor : "orange" ; folderType : "folder" ; folderEntries : 40 ; isFolderSelected : true ; targetFolderID : "" ; targetLabelIDs : "" ; }
-
- ListElement{ folderId : "28" ; folderName : "Label0" ; folderColor : "red" ; folderType : "label" ; folderEntries : 10 ; isFolderSelected : false ; targetFolderID : "" ; targetLabelIDs : "" ; }
- ListElement{ folderId : "29" ; folderName : "Label1" ; folderColor : "blue" ; folderType : "label" ; folderEntries : 11 ; isFolderSelected : true ; targetFolderID : "" ; targetLabelIDs : "" ; }
- ListElement{ folderId : "20" ; folderName : "Label2" ; folderColor : "green" ; folderType : "label" ; folderEntries : 12 ; isFolderSelected : false ; targetFolderID : "" ; targetLabelIDs : "" ; }
- ListElement{ folderId : "21" ; folderName : "Label3ToolongAndMustBeElidedSimilarToOnOfAccountsItJustNotNeedToBeThatLong" ; folderColor : "orange" ; folderType : "label" ; folderEntries : 40 ; isFolderSelected : true ; targetFolderID : "" ; targetLabelIDs : "" ; }
-
-
- function setFolderSelection ( folderId , toSelect ) { structureFuncs.setFolderSelection ( structurePM , folderId , toSelect ) }
- function selectType ( folderType , toSelect ) { structureFuncs.setTypeSelected ( structurePM , folderType , toSelect ) }
- function setFromToDate ( id , from, to ) { structureFuncs.setFromToDate ( structureExternal , id , from, to ) }
-
- function getID ( row ) { return row == -1 ? structurePM.globalOptions.folderId : structurePM.get(row) .folderId }
- function getById ( folderId ) { return structureFuncs.getById ( structurePM , folderId ) }
- function getName ( folderId ) { return structurePM.getById ( folderId ) .folderName }
- function getType ( folderId ) { return structurePM.getById ( folderId ) .folderType }
- function getColor ( folderId ) { return structurePM.getById ( folderId ) .folderColor }
- function getFrom ( folderId ) { return structurePM.getById ( folderId ) .fromDate }
- function getTo ( folderId ) { return structurePM.getById ( folderId ) .toDate }
- function getTargetLabelIDs ( folderId ) { return structurePM.getById ( folderId ) .getTargetLabelIDs }
- function hasFolderWithName ( folderName ) { return structureFuncs.hasFolderWithName ( structurePM , folderName ) }
-
- onDataChanged: {
- structureFuncs.updateSelection(structurePM)
- }
- }
-
- QtObject {
- id: structureFuncs
-
- function setFolderSelection (model, id , toSelect ) {
- console.log(" set folde sel", id, toSelect)
- for (var i= -1; i createLabelOrFolder", address, fname, fcolor, isFolder, sourceID)
- return (fname!="fail")
- }
-
- function loadImportReports(fname) {
- console.log("load import reports for ", fname)
- }
-
-
- onToggleAutoStart: {
- workAndClose("toggleAutoStart")
- isAutoStart = (isAutoStart!=0) ? 0 : 1
- console.log (" Test: toggleAutoStart "+isAutoStart)
- }
-
- function openReport() {
- Qt.openUrlExternally("file:///home/cuto/")
- }
-
- function sendImportReport(address, fname) {
- console.log("sending import report from ", address, " file ", fname)
- return !fname.includes("fail")
- }
-
- //onToggleAutoUpdate: {
- // workAndClose()
- // isAutoUpdate = (isAutoUpdate!=false) ? false : true
- // console.log (" Test: onToggleAutoUpdate "+isAutoUpdate)
- //}
- }
-}
diff --git a/internal/frontend/qt-common/Makefile.local b/internal/frontend/qt-common/Makefile.local
deleted file mode 100644
index 1ca530a4..00000000
--- a/internal/frontend/qt-common/Makefile.local
+++ /dev/null
@@ -1,6 +0,0 @@
-clean:
- rm -f moc.cpp
- rm -f moc.go
- rm -f moc.h
- rm -f moc_cgo*.go
- rm -f moc_moc.h
diff --git a/internal/frontend/qt-common/account_model.go b/internal/frontend/qt-common/account_model.go
deleted file mode 100644
index 81538b12..00000000
--- a/internal/frontend/qt-common/account_model.go
+++ /dev/null
@@ -1,237 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// +build build_qt
-
-package qtcommon
-
-import (
- "fmt"
-
- "github.com/therecipe/qt/core"
-)
-
-// AccountInfo is an element of model. It contains all data for one account and
-// it's aliases
-type AccountInfo struct {
- core.QObject
-
- _ string `property:"account"`
- _ string `property:"userID"`
- _ string `property:"status"`
- _ string `property:"hostname"`
- _ string `property:"password"`
- _ string `property:"security"`
- _ int `property:"portSMTP"`
- _ int `property:"portIMAP"`
- _ string `property:"aliases"`
- _ bool `property:"isExpanded"`
- _ bool `property:"isCombinedAddressMode"`
-}
-
-// Constants for AccountsModel property map
-const (
- Account = int(core.Qt__UserRole) + 1<= len(s.Accounts()) {
- return NewAccountInfo(nil)
- }
- return s.Accounts()[index]
-}
-
-// data return value for index and property
-func (s *AccountsModel) data(index *core.QModelIndex, property int) *core.QVariant {
- if !index.IsValid() {
- return core.NewQVariant()
- }
-
- if index.Row() >= len(s.Accounts()) {
- return core.NewQVariant()
- }
-
- var accountInfo = s.Accounts()[index.Row()]
-
- switch property {
- case Account:
- return NewQVariantString(accountInfo.Account())
- case UserID:
- return NewQVariantString(accountInfo.UserID())
- case Status:
- return NewQVariantString(accountInfo.Status())
- case Hostname:
- return NewQVariantString(accountInfo.Hostname())
- case Password:
- return NewQVariantString(accountInfo.Password())
- case Security:
- return NewQVariantString(accountInfo.Security())
- case PortIMAP:
- return NewQVariantInt(accountInfo.PortIMAP())
- case PortSMTP:
- return NewQVariantInt(accountInfo.PortSMTP())
- case Aliases:
- return NewQVariantString(accountInfo.Aliases())
- case IsExpanded:
- return NewQVariantBool(accountInfo.IsExpanded())
- case IsCombinedAddressMode:
- return NewQVariantBool(accountInfo.IsCombinedAddressMode())
- default:
- return core.NewQVariant()
- }
-}
-
-// rowCount returns the dimension of model: number of rows is equivalent to number of items in list.
-func (s *AccountsModel) rowCount(parent *core.QModelIndex) int {
- return len(s.Accounts())
-}
-
-// columnCount returns the dimension of model: AccountsModel has only one column.
-func (s *AccountsModel) columnCount(parent *core.QModelIndex) int {
- return 1
-}
-
-// roleNames returns the names of available item properties.
-func (s *AccountsModel) roleNames() map[int]*core.QByteArray {
- return s.Roles()
-}
-
-// addAccount is connected to the addAccount slot.
-func (s *AccountsModel) addAccount(accountInfo *AccountInfo) {
- s.BeginInsertRows(core.NewQModelIndex(), len(s.Accounts()), len(s.Accounts()))
- s.SetAccounts(append(s.Accounts(), accountInfo))
- s.SetCount(len(s.Accounts()))
- s.EndInsertRows()
-}
-
-// toggleIsAvailable is connected to toggleIsAvailable slot.
-func (s *AccountsModel) toggleIsAvailable(row int) {
- var accountInfo = s.Accounts()[row]
- currentStatus := accountInfo.Status()
- if currentStatus == "active" {
- accountInfo.SetStatus("disabled")
- } else if currentStatus == "disabled" {
- accountInfo.SetStatus("active")
- } else {
- accountInfo.SetStatus("error")
- }
- var pIndex = s.Index(row, 0, core.NewQModelIndex())
- s.DataChanged(pIndex, pIndex, []int{Status})
-}
-
-// removeAccount is connected to removeAccount slot.
-func (s *AccountsModel) removeAccount(row int) {
- s.BeginRemoveRows(core.NewQModelIndex(), row, row)
- s.SetAccounts(append(s.Accounts()[:row], s.Accounts()[row+1:]...))
- s.SetCount(len(s.Accounts()))
- s.EndRemoveRows()
-}
-
-// Clear removes all items in model.
-func (s *AccountsModel) Clear() {
- s.BeginRemoveRows(core.NewQModelIndex(), 0, len(s.Accounts()))
- s.SetAccounts(s.Accounts()[0:0])
- s.SetCount(len(s.Accounts()))
- s.EndRemoveRows()
-}
-
-// Dump prints the content of account models to console.
-func (s *AccountsModel) Dump() {
- fmt.Printf("Dimensions rows %d cols %d\n", s.rowCount(nil), s.columnCount(nil))
- for iAcc := 0; iAcc < s.rowCount(nil); iAcc++ {
- var accountInfo = s.Accounts()[iAcc]
- fmt.Printf(" %d. %s\n", iAcc, accountInfo.Account())
- }
-}
diff --git a/internal/frontend/qt-common/accounts.go b/internal/frontend/qt-common/accounts.go
deleted file mode 100644
index 29609a65..00000000
--- a/internal/frontend/qt-common/accounts.go
+++ /dev/null
@@ -1,259 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// +build build_qt
-
-package qtcommon
-
-import (
- "context"
- "fmt"
- "strings"
- "sync"
-
- "github.com/ProtonMail/proton-bridge/internal/bridge"
- "github.com/ProtonMail/proton-bridge/internal/config/settings"
- "github.com/ProtonMail/proton-bridge/internal/events"
- "github.com/ProtonMail/proton-bridge/internal/frontend/types"
- "github.com/ProtonMail/proton-bridge/pkg/keychain"
- "github.com/ProtonMail/proton-bridge/pkg/pmapi"
-)
-
-// QMLer sends signals to GUI
-type QMLer interface {
- ProcessFinished()
- NotifyHasNoKeychain()
- SetConnectionStatus(bool)
- SetAddAccountWarning(string, int)
- NotifyBubble(int, string)
- EmitEvent(string, string)
- Quit()
-
- CanNotReachAPI() string
- WrongMailboxPassword() string
-}
-
-// Accounts holds functionality of users
-type Accounts struct {
- Model *AccountsModel
- qml QMLer
- um types.UserManager
- settings *settings.Settings
-
- authClient pmapi.Client
- auth *pmapi.Auth
-
- LatestUserID string
- accountMutex sync.Mutex
- restarter types.Restarter
-}
-
-// SetupAccounts will create Model and set QMLer and UserManager
-func (a *Accounts) SetupAccounts(qml QMLer, um types.UserManager, restarter types.Restarter) {
- a.Model = NewAccountsModel(nil)
- a.qml = qml
- a.um = um
- a.restarter = restarter
-}
-
-// LoadAccounts refreshes the current account list in GUI
-func (a *Accounts) LoadAccounts() {
- a.accountMutex.Lock()
- defer a.accountMutex.Unlock()
-
- a.Model.Clear()
-
- users := a.um.GetUsers()
-
- // If there are no active accounts.
- if len(users) == 0 {
- log.Info("No active accounts")
- return
- }
- for _, user := range users {
- accInfo := NewAccountInfo(nil)
- username := user.Username()
- if username == "" {
- username = user.ID()
- }
- accInfo.SetAccount(username)
-
- // Set status.
- if user.IsConnected() {
- accInfo.SetStatus("connected")
- } else {
- accInfo.SetStatus("disconnected")
- }
-
- // Set login info.
- accInfo.SetUserID(user.ID())
- accInfo.SetHostname(bridge.Host)
- accInfo.SetPassword(user.GetBridgePassword())
- if a.settings != nil {
- accInfo.SetPortIMAP(a.settings.GetInt(settings.IMAPPortKey))
- accInfo.SetPortSMTP(a.settings.GetInt(settings.SMTPPortKey))
- }
-
- // Set aliases.
- accInfo.SetAliases(strings.Join(user.GetAddresses(), ";"))
- accInfo.SetIsExpanded(user.ID() == a.LatestUserID)
- accInfo.SetIsCombinedAddressMode(user.IsCombinedAddressMode())
-
- a.Model.addAccount(accInfo)
- }
-
- // Updated can clear.
- a.LatestUserID = ""
-}
-
-// ClearCache signal to remove all DB files
-func (a *Accounts) ClearCache() {
- defer a.qml.ProcessFinished()
- if err := a.um.ClearData(); err != nil {
- log.Error("While clearing cache: ", err)
- }
- // Clearing data removes everything (db, preferences, ...)
- // so everything has to be stopped and started again.
- a.restarter.SetToRestart()
- a.qml.Quit()
-}
-
-// ClearKeychain signal remove all accounts from keychains
-func (a *Accounts) ClearKeychain() {
- defer a.qml.ProcessFinished()
- for _, user := range a.um.GetUsers() {
- if err := a.um.DeleteUser(user.ID(), false); err != nil {
- log.Error("While deleting user: ", err)
- if err == keychain.ErrNoKeychain { // Probably not needed anymore.
- a.qml.NotifyHasNoKeychain()
- }
- }
- }
-}
-
-// LogoutAccount signal to remove account
-func (a *Accounts) LogoutAccount(iAccount int) {
- defer a.qml.ProcessFinished()
- userID := a.Model.get(iAccount).UserID()
- user, err := a.um.GetUser(userID)
- if err != nil {
- log.Error("While logging out ", userID, ": ", err)
- return
- }
- if err := user.Logout(); err != nil {
- log.Error("While logging out ", userID, ": ", err)
- }
-}
-
-func (a *Accounts) showLoginError(err error, scope string) bool {
- if err == nil {
- a.qml.SetConnectionStatus(true) // If we are here connection is ok.
- return false
- }
- log.Warnf("%s: %v", scope, err)
- if err == pmapi.ErrNoConnection {
- a.qml.SetConnectionStatus(false)
- SendNotification(a.qml, TabAccount, a.qml.CanNotReachAPI())
- a.qml.ProcessFinished()
- return true
- }
- a.qml.SetConnectionStatus(true) // If we are here connection is ok.
- if err == pmapi.ErrUpgradeApplication {
- return true
- }
- a.qml.SetAddAccountWarning(err.Error(), -1)
- return true
-}
-
-// Login signal returns:
-// -1: when error occurred
-// 0: when no 2FA and no MBOX
-// 1: when has 2FA
-// 2: when has no 2FA but have MBOX
-func (a *Accounts) Login(login, password string) int {
- var err error
- a.authClient, a.auth, err = a.um.Login(login, []byte(password))
- if a.showLoginError(err, "login") {
- return -1
- }
- if a.auth.HasTwoFactor() {
- return 1
- }
- if a.auth.HasMailboxPassword() {
- return 2
- }
- return 0 // No 2FA, no mailbox password.
-}
-
-// Auth2FA returns:
-// -1 : error (use SetAddAccountWarning to show message)
-// 0 : single password mode
-// 1 : two password mode
-func (a *Accounts) Auth2FA(twoFacAuth string) int {
- var err error
- if a.auth == nil || a.authClient == nil {
- err = fmt.Errorf("missing authentication in auth2FA %p %p", a.auth, a.authClient)
- } else {
- err = a.authClient.Auth2FA(context.Background(), twoFacAuth)
- }
-
- if a.showLoginError(err, "auth2FA") {
- return -1
- }
-
- if a.auth.HasMailboxPassword() {
- return 1 // Ask for mailbox password.
- }
- return 0 // One password.
-}
-
-// AddAccount signal to add an account. It should close login modal
-// ProcessFinished if ok.
-func (a *Accounts) AddAccount(mailboxPassword string) int {
- if a.auth == nil || a.authClient == nil {
- log.Errorf("Missing authentication in addAccount %p %p", a.auth, a.authClient)
- a.qml.SetAddAccountWarning(a.qml.WrongMailboxPassword(), -2)
- return -1
- }
-
- user, err := a.um.FinishLogin(a.authClient, a.auth, []byte(mailboxPassword))
- if err != nil {
- log.WithError(err).Error("Login was unsuccessful")
- a.qml.SetAddAccountWarning("Failure: "+err.Error(), -2)
- return -1
- }
-
- a.LatestUserID = user.ID()
- a.qml.EmitEvent(events.UserRefreshEvent, user.ID())
- a.qml.ProcessFinished()
- return 0
-}
-
-// DeleteAccount by index in Model
-func (a *Accounts) DeleteAccount(iAccount int, removePreferences bool) {
- defer a.qml.ProcessFinished()
- userID := a.Model.get(iAccount).UserID()
- if err := a.um.DeleteUser(userID, removePreferences); err != nil {
- log.Warn("deleteUser: cannot remove user: ", err)
- if err == keychain.ErrNoKeychain {
- a.qml.NotifyHasNoKeychain()
- return
- }
- SendNotification(a.qml, TabSettings, err.Error())
- return
- }
-}
diff --git a/internal/frontend/qt-common/common.cpp b/internal/frontend/qt-common/common.cpp
deleted file mode 100644
index 79091f0e..00000000
--- a/internal/frontend/qt-common/common.cpp
+++ /dev/null
@@ -1,30 +0,0 @@
-// +build build_qt
-
-#include "common.h"
-#include "_cgo_export.h"
-
-#include
-#include
-#include
-#include
-#include
-
-void messageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg)
-{
- Q_UNUSED( type )
- Q_UNUSED( context )
- QByteArray localMsg = msg.toUtf8().prepend("WHITESPACE");
- logMsgPacked(
- const_cast( (localMsg.constData()) +10 ),
- localMsg.size()-10
- );
- //printf("Handler: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
-}
-void InstallMessageHandler() {
- qInstallMessageHandler(messageHandler);
-}
-
-
-void RegisterTypes() {
- qRegisterMetaType >();
-}
diff --git a/internal/frontend/qt-common/common.go b/internal/frontend/qt-common/common.go
deleted file mode 100644
index f6281d4b..00000000
--- a/internal/frontend/qt-common/common.go
+++ /dev/null
@@ -1,115 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// +build build_qt
-
-package qtcommon
-
-//#include "common.h"
-import "C"
-
-import (
- "bufio"
- "os"
- "time"
-
- "github.com/sirupsen/logrus"
- "github.com/therecipe/qt/core"
-)
-
-var log = logrus.WithField("pkg", "frontend/qt-common")
-var logQML = logrus.WithField("pkg", "frontend/qml")
-
-// RegisterTypes for vector of ints
-func RegisterTypes() { // need to fix test message
- C.RegisterTypes()
-}
-
-func installMessageHandler() {
- C.InstallMessageHandler()
-}
-
-//export logMsgPacked
-func logMsgPacked(data *C.char, len C.int) {
- logQML.Warn(C.GoStringN(data, len))
-}
-
-// QtSetupCoreAndControls hanldes global setup of Qt.
-// Should be called once per program. Probably once per thread is fine.
-func QtSetupCoreAndControls(programName, programVersion string) {
- installMessageHandler()
- // Core setup.
- core.QCoreApplication_SetApplicationName(programName)
- core.QCoreApplication_SetApplicationVersion(programVersion)
- // High DPI scaling for windows.
- core.QCoreApplication_SetAttribute(core.Qt__AA_EnableHighDpiScaling, false)
- // Software OpenGL: to avoid dedicated GPU.
- core.QCoreApplication_SetAttribute(core.Qt__AA_UseSoftwareOpenGL, true)
- // Basic style for QuickControls2 objects.
- //quickcontrols2.QQuickStyle_SetStyle("material")
-}
-
-// NewQByteArrayFromString is wrapper for new QByteArray from string
-func NewQByteArrayFromString(name string) *core.QByteArray {
- return core.NewQByteArray2(name, -1)
-}
-
-// NewQVariantString is wrapper for QVariant alocator String
-func NewQVariantString(data string) *core.QVariant {
- return core.NewQVariant1(data)
-}
-
-// NewQVariantStringArray is wrapper for QVariant alocator String Array
-func NewQVariantStringArray(data []string) *core.QVariant {
- return core.NewQVariant1(data)
-}
-
-// NewQVariantBool is wrapper for QVariant alocator Bool
-func NewQVariantBool(data bool) *core.QVariant {
- return core.NewQVariant1(data)
-}
-
-// NewQVariantInt is wrapper for QVariant alocator Int
-func NewQVariantInt(data int) *core.QVariant {
- return core.NewQVariant1(data)
-}
-
-// NewQVariantLong is wrapper for QVariant alocator Int64
-func NewQVariantLong(data int64) *core.QVariant {
- return core.NewQVariant1(data)
-}
-
-// Pause used to show GUI tests
-func Pause() {
- time.Sleep(500 * time.Millisecond)
-}
-
-// Longer pause used to diplay GUI tests
-func PauseLong() {
- time.Sleep(3 * time.Second)
-}
-
-// FIXME: Not working in test...
-func WaitForEnter() {
- log.Print("Press 'Enter' to continue...")
- bufio.NewReader(os.Stdin).ReadBytes('\n')
-}
-
-type Listener interface {
- Add(string, chan<- string)
- RetryEmit(string)
-}
diff --git a/internal/frontend/qt-common/common.h b/internal/frontend/qt-common/common.h
deleted file mode 100644
index 699419fa..00000000
--- a/internal/frontend/qt-common/common.h
+++ /dev/null
@@ -1,21 +0,0 @@
-
-#pragma once
-
-#ifndef GO_LOG_H
-#define GO_LOG_H
-
-#include
-
-#ifdef __cplusplus
-extern "C" {
-#endif // C++
-
- void InstallMessageHandler();
- void RegisterTypes();
- ;
-
-#ifdef __cplusplus
-}
-#endif // C++
-
-#endif // LOG
diff --git a/internal/frontend/qt-common/notification.go b/internal/frontend/qt-common/notification.go
deleted file mode 100644
index 869989db..00000000
--- a/internal/frontend/qt-common/notification.go
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// +build build_qt
-
-package qtcommon
-
-// Positions of notification bubble
-const (
- TabAccount = 0
- TabSettings = 1
- TabHelp = 2
- TabQuit = 4
- TabUpdates = 100
- TabAddAccount = -1
-)
-
-// Notifier show bubble notification at postion marked by int
-type Notifier interface {
- NotifyBubble(int, string)
-}
-
-// SendNotification unifies notification in GUI
-func SendNotification(qml Notifier, tabIndex int, msg string) {
- qml.NotifyBubble(tabIndex, msg)
-}
diff --git a/internal/frontend/qt-ie/Makefile.local b/internal/frontend/qt-ie/Makefile.local
deleted file mode 100644
index 71a9058b..00000000
--- a/internal/frontend/qt-ie/Makefile.local
+++ /dev/null
@@ -1,60 +0,0 @@
-QMLfiles=$(shell find ../qml/ -name "*.qml") $(shell find ../qml/ -name "qmldir")
-FontAwesome=${CURDIR}/../share/fontawesome-webfont.ttf
-ImageDir=${CURDIR}/../share/icons
-Icons=$(shell find ${ImageDir} -name "*.png")
-Icons+= share/images/folder_open.png share/images/envelope_open.png
-MocDependencies= ./ui.go ./account_model.go ./folder_structure.go ./folder_functions.go
-## EnumDependecies= ../backend/errors/errors.go ../backend/progress.go ../backend/source/enum.go ../frontend/enums.go
-
-all: ../qml/ImportExportUI/images moc.go ../qml/GuiIE.qml qmlcheck rcc.cpp
-
-## ./qml/GuiIE.qml: enums.sh ${EnumDependecies}
-## ./enums.sh
-
-../qml/ProtonUI/fontawesome.ttf:
- ln -sf ${FontAwesome} $@
-../qml/ProtonUI/images:
- ln -sf ${ImageDir} $@
-../qml/ImportExportUI/images:
- ln -sf ${ImageDir} $@
-
-translate.ts: ${QMLfiles}
- lupdate -recursive qml/ -ts $@
-
-rcc.cpp: ${QMLfiles} ${Icons} resources.qrc
- rm -f rcc.cpp rcc.qrc && qtrcc -o .
-
-
-qmltest:
- qmltestrunner -eventdelay 500 -import ../qml/
-qmlcheck: ../qml/ProtonUI/fontawesome.ttf ../qml/ImportExportUI/images ../qml/ProtonUI/images
- qmlscene -verbose -I ../qml/ -f ../qml/tst_GuiIE.qml --quit
-qmlpreview: ../qml/ProtonUI/fontawesome.ttf ../qml/ImportExportUI/images ../qml/ProtonUI/images
- rm -f ../qml/*.qmlc ../qml/ProtonUI/*.qmlc ../qml/ImportExportUI/*.qmlc
- qmlscene -verbose -I ../qml/ -f ../qml/tst_GuiIE.qml 2>&1
-
-test: qmlcheck moc.go rcc.cpp
- go test -v
-
-moc.go: ${MocDependencies}
- qtmoc
-
-clean:
- rm -rf linux/
- rm -rf darwin/
- rm -rf windows/
- rm -rf deploy/
- rm -f moc.cpp
- rm -f moc.go
- rm -f moc.h
- rm -f moc_cgo*.go
- rm -f moc_moc.h
- rm -f rcc.cpp
- rm -f rcc.qrc
- rm -f rcc_cgo*.go
- rm -f ../rcc.cpp
- rm -f ../rcc.qrc
- rm -f ../rcc_cgo*.go
- rm -rf ../qml/ProtonUI/images
- rm -f ../qml/ProtonUI/fontawesome.ttf
- find ../qml -name *.qmlc -exec rm {} \;
diff --git a/internal/frontend/qt-ie/README.md b/internal/frontend/qt-ie/README.md
deleted file mode 100644
index 07dc9205..00000000
--- a/internal/frontend/qt-ie/README.md
+++ /dev/null
@@ -1,55 +0,0 @@
-# ProtonMail Import-Export Qt interface
-Import-Export uses [Qt](https://www.qt.io) framework for creating appealing graphical
-user interface. Package [therecipe/qt](https://github.com/therecipe/qt) is used
-to implement Qt into [Go](https://www.goglang.com).
-
-
-# For developers
-The GUI is designed inside QML files. Communication with backend is done via
-[frontend.go](./frontend.go). The API documentation is done via `go-doc`.
-
-## Setup
-* if you don't have the system wide `go-1.8.1` download, install localy (e.g.
- `~/build/go-1.8.1`) and setup:
-
- export GOROOT=~/build/go-1.8.1/go
- export PATH=$GOROOT/bin:$PATH
-
-* go to your working directory and export `$GOPATH`
-
- export GOPATH=`Pwd`
- mkdir -p $GOPATH/bin
- export PATH=$PATH:$GOPATH/bin
-
-
-* if you dont have system wide `Qt-5.8.0`
- [download](https://download.qt.io/official_releases/qt/5.8/5.8.0/qt-opensource-linux-x64-5.8.0.run),
- install locally (e.g. `~/build/qt/qt-5.8.0`) and setup:
-
- export QT_DIR=~/build/qt/qt-5.8.0
- export PATH=$QT_DIR/5.8/gcc_64/bin:$PATH
-
-* `Go-Qt` setup (installation is system dependent see
- [therecipe/qt/README](https://github.com/therecipe/qt/blob/master/README.md)
- for details)
-
- go get -u -v github.com/therecipe/qt/cmd/...
- $GOPATH/bin/qtsetup
-
-## Compile
-* it is necessary to compile the Qt-C++ with go for resources and meta-objects
-
- make -f Makefile.local
-
-* FIXME the rcc file is implicitly generated with `package main`. This needs to
- be changed to `package qtie` manually
-* check that user interface is working
-
- make -f Makefile.local test
-
-## Test
-
- make -f Makefile.local qmlpreview
-
-## Deploy
-* before compilation of Import-Export it is necessary to run compilation of Qt-C++ part (done in makefile)
diff --git a/internal/frontend/qt-ie/enums.go b/internal/frontend/qt-ie/enums.go
deleted file mode 100644
index 72eaa622..00000000
--- a/internal/frontend/qt-ie/enums.go
+++ /dev/null
@@ -1,120 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// +build build_qt
-
-package qtie
-
-import (
- "github.com/therecipe/qt/core"
-)
-
-// Folder Type
-const (
- FolderTypeSystem = ""
- FolderTypeLabel = "label"
- FolderTypeFolder = "folder"
- FolderTypeExternal = "external"
-)
-
-// Status
-const (
- StatusNoInternet = "noInternet"
- StatusCheckingInternet = "internetCheck"
- StatusNewVersionAvailable = "oldVersion"
- StatusUpToDate = "upToDate"
- StatusForceUpdate = "forceupdate"
-)
-
-// Constants for data map
-const (
- // Account info
- Account = int(core.Qt__UserRole) + 1 + iota // 256 + 1 = 257
- Status // 258
- Password // 259
- Aliases // ...
- IsExpanded
- // Folder info
- FolderId
- FolderName
- FolderColor
- FolderType
- FolderEntries
- IsFolderSelected
- FolderFromDate
- FolderToDate
- TargetFolderID
- TargetLabelIDs
- // Error list
- MailSubject
- MailDate
- MailFrom
- InputFolder
- ErrorMessage
- // Transfer rules mbox
- MboxSelectedIndex
- MboxIsActive
- MboxID
- MboxName
- MboxType
- MboxColor
- // Transfer Rules
- RuleTargetLabelColors
- RuleFromDate
- RuleToDate
-)
-
-const (
- // This should match enums in GuiIE.qml
- errUnknownError = 0
- errEventAPILogout = 1
- errUpdateAPI = 2
- errUpdateJSON = 3
- errUserAuth = 4
- errQApplication = 18
- errEmailExportFailed = 6
- errEmailExportMissing = 7
- errNothingToImport = 8
- errEmailImportFailed = 12
- errDraftImportFailed = 13
- errDraftLabelFailed = 14
- errEncryptMessageAttachment = 15
- errEncryptMessage = 16
- errNoInternetWhileImport = 17
- errUnlockUser = 5
- errSourceMessageNotSelected = 19
- errCannotParseMail = 5000
- errWrongLoginOrPassword = 5001
- errWrongServerPathOrPort = 5002
- errWrongAuthMethod = 5003
- errIMAPFetchFailed = 5004
- errLocalSourceLoadFailed = 1000
- errPMLoadFailed = 1001
- errRemoteSourceLoadFailed = 1002
- errLoadAccountList = 1005
- errExit = 1006
- errRetry = 1007
- errAsk = 1008
- errImportFailed = 1009
- errCreateLabelFailed = 1010
- errCreateFolderFailed = 1011
- errUpdateLabelFailed = 1012
- errUpdateFolderFailed = 1013
- errFillFolderName = 1014
- errSelectFolderColor = 1015
- errNoInternet = 1016
-)
diff --git a/internal/frontend/qt-ie/error_list.go b/internal/frontend/qt-ie/error_list.go
deleted file mode 100644
index 2012b3ac..00000000
--- a/internal/frontend/qt-ie/error_list.go
+++ /dev/null
@@ -1,103 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// +build build_qt
-
-package qtie
-
-import (
- qtcommon "github.com/ProtonMail/proton-bridge/internal/frontend/qt-common"
- "github.com/ProtonMail/proton-bridge/internal/transfer"
- "github.com/therecipe/qt/core"
-)
-
-func init() {
- ErrorListModel_QRegisterMetaType()
-}
-
-// ErrorListModel to sending error details to Qt
-type ErrorListModel struct {
- core.QAbstractListModel
-
- // Qt list model
- _ func() `constructor:"init"`
- _ map[int]*core.QByteArray `property:"roles"`
- _ int `property:"count"`
-
- Progress *transfer.Progress
- records []*transfer.MessageStatus
-}
-
-func (e *ErrorListModel) init() {
- e.SetRoles(map[int]*core.QByteArray{
- MailSubject: qtcommon.NewQByteArrayFromString("mailSubject"),
- MailDate: qtcommon.NewQByteArrayFromString("mailDate"),
- MailFrom: qtcommon.NewQByteArrayFromString("mailFrom"),
- InputFolder: qtcommon.NewQByteArrayFromString("inputFolder"),
- ErrorMessage: qtcommon.NewQByteArrayFromString("errorMessage"),
- })
- // basic QAbstractListModel mehods
- e.ConnectData(e.data)
- e.ConnectRowCount(e.rowCount)
- e.ConnectColumnCount(e.columnCount)
- e.ConnectRoleNames(e.roleNames)
-}
-
-func (e *ErrorListModel) data(index *core.QModelIndex, role int) *core.QVariant {
- if !index.IsValid() {
- return core.NewQVariant()
- }
-
- if index.Row() >= len(e.records) {
- return core.NewQVariant()
- }
-
- var r = e.records[index.Row()]
-
- switch role {
- case MailSubject:
- return qtcommon.NewQVariantString(r.Subject)
- case MailDate:
- if r.Time.IsZero() {
- return qtcommon.NewQVariantString("Unavailable")
- }
- return qtcommon.NewQVariantString(r.Time.String())
- case MailFrom:
- return qtcommon.NewQVariantString(r.From)
- case InputFolder:
- return qtcommon.NewQVariantString(r.SourceID)
- case ErrorMessage:
- return qtcommon.NewQVariantString(r.GetErrorMessage())
- default:
- return core.NewQVariant()
- }
-}
-
-func (e *ErrorListModel) rowCount(parent *core.QModelIndex) int { return len(e.records) }
-func (e *ErrorListModel) columnCount(parent *core.QModelIndex) int { return 1 }
-func (e *ErrorListModel) roleNames() map[int]*core.QByteArray { return e.Roles() }
-
-func (e *ErrorListModel) load() {
- if e.Progress == nil {
- log.Error("Progress not connected")
- return
- }
-
- e.BeginResetModel()
- e.records = e.Progress.GetFailedMessages()
- e.EndResetModel()
-}
diff --git a/internal/frontend/qt-ie/export.go b/internal/frontend/qt-ie/export.go
deleted file mode 100644
index a91b3ea3..00000000
--- a/internal/frontend/qt-ie/export.go
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// +build build_qt
-
-package qtie
-
-import (
- "github.com/ProtonMail/proton-bridge/internal/transfer"
- "github.com/pkg/errors"
-)
-
-const (
- TypeEML = "EML"
- TypeMBOX = "MBOX"
-)
-
-func (f *FrontendQt) LoadStructureForExport(username, addressOrID string) {
- errCode := errUnknownError
- var err error
- defer func() {
- if err != nil {
- f.showError(errCode, errors.Wrap(err, "failed to load structure for "+addressOrID))
- f.Qml.ExportStructureLoadFinished(false)
- } else {
- f.Qml.ExportStructureLoadFinished(true)
- }
- }()
-
- if f.transfer, err = f.ie.GetEMLExporter(username, addressOrID, ""); err != nil {
- // The only error can be problem to load PM user and address.
- errCode = errPMLoadFailed
- return
- }
-
- // Export has only one option to set time limits--by global time range.
- // In case user changes file or because of some bug global time is saved
- // to all rules, let's clear it, because there is no way to show it in
- // GUI and user would be confused and see it does not work at all.
- for _, rule := range f.transfer.GetRules() {
- isActive := rule.Active
- f.transfer.SetRule(rule.SourceMailbox, rule.TargetMailboxes, 0, 0)
- if !isActive {
- f.transfer.UnsetRule(rule.SourceMailbox)
- }
- }
-
- f.TransferRules.setTransfer(f.transfer)
-}
-
-func (f *FrontendQt) StartExport(rootPath, login, fileType string, attachEncryptedBody bool) {
- var target transfer.TargetProvider
- if fileType == TypeEML {
- target = transfer.NewEMLProvider(rootPath)
- } else if fileType == TypeMBOX {
-
- target = transfer.NewMBOXProvider(rootPath)
- } else {
- log.Errorln("Wrong file format:", fileType)
- return
- }
- f.transfer.ChangeTarget(target)
- f.transfer.SetSkipEncryptedMessages(!attachEncryptedBody)
- progress := f.transfer.Start()
- f.setProgressManager(progress)
-}
diff --git a/internal/frontend/qt-ie/folder_functions.go b/internal/frontend/qt-ie/folder_functions.go
deleted file mode 100644
index 199f34bd..00000000
--- a/internal/frontend/qt-ie/folder_functions.go
+++ /dev/null
@@ -1,531 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// +build build_qt
-
-package qtie
-
-import (
- "errors"
- "strings"
-
- qtcommon "github.com/ProtonMail/proton-bridge/internal/frontend/qt-common"
- "github.com/ProtonMail/proton-bridge/internal/transfer"
- "github.com/ProtonMail/proton-bridge/pkg/pmapi"
- "github.com/therecipe/qt/core"
-)
-
-const (
- GlobalOptionIndex = -1
-)
-
-var AllFolderInfoRoles = []int{
- FolderId,
- FolderName,
- FolderColor,
- FolderType,
- FolderEntries,
- IsFolderSelected,
- FolderFromDate,
- FolderToDate,
- TargetFolderID,
- TargetLabelIDs,
-}
-
-func getTargetHashes(mboxes []transfer.Mailbox) (targetFolderID, targetLabelIDs string) {
- for _, targetMailbox := range mboxes {
- if targetMailbox.IsExclusive {
- targetFolderID = targetMailbox.Hash()
- } else {
- targetLabelIDs += targetMailbox.Hash() + ";"
- }
- }
-
- targetLabelIDs = strings.Trim(targetLabelIDs, ";")
- return
-}
-
-func newFolderInfo(mbox transfer.Mailbox, rule *transfer.Rule) *FolderInfo {
- targetFolderID, targetLabelIDs := getTargetHashes(rule.TargetMailboxes)
-
- entry := &FolderInfo{
- mailbox: mbox,
- FolderEntries: 1,
- FromDate: rule.FromTime,
- ToDate: rule.ToTime,
- IsFolderSelected: rule.Active,
- TargetFolderID: targetFolderID,
- TargetLabelIDs: targetLabelIDs,
- }
-
- entry.FolderType = FolderTypeSystem
- if !pmapi.IsSystemLabel(mbox.ID) {
- if mbox.IsExclusive {
- entry.FolderType = FolderTypeFolder
- } else {
- entry.FolderType = FolderTypeLabel
- }
- }
-
- return entry
-}
-
-func (s *FolderStructure) saveRule(info *FolderInfo) error {
- if s.transfer == nil {
- return errors.New("missing transfer")
- }
- sourceMbox := info.mailbox
- if !info.IsFolderSelected {
- s.transfer.UnsetRule(sourceMbox)
- return nil
- }
- allTargetMboxes, err := s.transfer.TargetMailboxes()
- if err != nil {
- return err
- }
- var targetMboxes []transfer.Mailbox
- for _, target := range allTargetMboxes {
- targetHash := target.Hash()
- if info.TargetFolderID == targetHash || strings.Contains(info.TargetLabelIDs, targetHash) {
- targetMboxes = append(targetMboxes, target)
- }
- }
-
- return s.transfer.SetRule(sourceMbox, targetMboxes, info.FromDate, info.ToDate)
-}
-
-func (s *FolderInfo) updateTargetLabelIDs(targetLabelsSet map[string]struct{}) {
- targets := []string{}
- for key := range targetLabelsSet {
- targets = append(targets, key)
- }
- s.TargetLabelIDs = strings.Join(targets, ";")
-}
-
-func (s *FolderInfo) AddTargetLabel(targetID string) {
- if targetID == "" {
- return
- }
- targetLabelsSet := s.getSetOfLabels()
- targetLabelsSet[targetID] = struct{}{}
- s.updateTargetLabelIDs(targetLabelsSet)
-}
-
-func (s *FolderInfo) RemoveTargetLabel(targetID string) {
- if targetID == "" {
- return
- }
- targetLabelsSet := s.getSetOfLabels()
- delete(targetLabelsSet, targetID)
- s.updateTargetLabelIDs(targetLabelsSet)
-}
-
-func (s *FolderInfo) IsType(askType string) bool {
- return s.FolderType == askType
-}
-
-func (s *FolderInfo) getSetOfLabels() (uniqSet map[string]struct{}) {
- uniqSet = make(map[string]struct{})
- for _, label := range s.TargetLabelIDList() {
- uniqSet[label] = struct{}{}
- }
- return
-}
-
-func (s *FolderInfo) TargetLabelIDList() []string {
- return strings.FieldsFunc(
- s.TargetLabelIDs,
- func(c rune) bool { return c == ';' },
- )
-}
-
-// Get data
-func (s *FolderStructure) data(index *core.QModelIndex, role int) *core.QVariant {
- row, isValid := index.Row(), index.IsValid()
- if !isValid || row >= s.getCount() {
- log.Warnln("Wrong index", isValid, row)
- return core.NewQVariant()
- }
-
- var f = s.get(row)
-
- switch role {
- case FolderId:
- return qtcommon.NewQVariantString(f.mailbox.Hash())
- case FolderName, int(core.Qt__DisplayRole):
- return qtcommon.NewQVariantString(f.mailbox.Name)
- case FolderColor:
- return qtcommon.NewQVariantString(f.mailbox.Color)
- case FolderType:
- return qtcommon.NewQVariantString(f.FolderType)
- case FolderEntries:
- return qtcommon.NewQVariantInt(f.FolderEntries)
- case FolderFromDate:
- return qtcommon.NewQVariantLong(f.FromDate)
- case FolderToDate:
- return qtcommon.NewQVariantLong(f.ToDate)
- case IsFolderSelected:
- return qtcommon.NewQVariantBool(f.IsFolderSelected)
- case TargetFolderID:
- return qtcommon.NewQVariantString(f.TargetFolderID)
- case TargetLabelIDs:
- return qtcommon.NewQVariantString(f.TargetLabelIDs)
- default:
- log.Warnln("Wrong role", role)
- return core.NewQVariant()
- }
-}
-
-// Get header data (table view, tree view)
-func (s *FolderStructure) headerData(section int, orientation core.Qt__Orientation, role int) *core.QVariant {
- if role != int(core.Qt__DisplayRole) {
- return core.NewQVariant()
- }
-
- if orientation == core.Qt__Horizontal {
- return qtcommon.NewQVariantString("Column")
- }
-
- return qtcommon.NewQVariantString("Row")
-}
-
-// Flags is editable
-func (s *FolderStructure) flags(index *core.QModelIndex) core.Qt__ItemFlag {
- if !index.IsValid() {
- return core.Qt__ItemIsEnabled
- }
-
- // can do here also: core.NewQAbstractItemModelFromPointer(s.Pointer()).Flags(index) | core.Qt__ItemIsEditable
- // or s.FlagsDefault(index) | core.Qt__ItemIsEditable
- return core.Qt__ItemIsEnabled | core.Qt__ItemIsSelectable | core.Qt__ItemIsEditable
-}
-
-// Set data
-func (s *FolderStructure) setData(index *core.QModelIndex, value *core.QVariant, role int) bool {
- log.Debugf("SET DATA %d", role)
- if !index.IsValid() {
- return false
- }
- if index.Row() < GlobalOptionIndex || index.Row() > s.getCount() || index.Column() != 1 {
- return false
- }
- item := s.get(index.Row())
- t := true
- switch role {
- case FolderId, FolderType:
- log.
- WithField("structure", s).
- WithField("row", index.Row()).
- WithField("column", index.Column()).
- WithField("role", role).
- WithField("isEdit", role == int(core.Qt__EditRole)).
- Warn("Set constant role forbiden")
- case FolderName:
- item.mailbox.Name = value.ToString()
- case FolderColor:
- item.mailbox.Color = value.ToString()
- case FolderEntries:
- item.FolderEntries = value.ToInt(&t)
- case FolderFromDate:
- item.FromDate = value.ToLongLong(&t)
- case FolderToDate:
- item.ToDate = value.ToLongLong(&t)
- case IsFolderSelected:
- item.IsFolderSelected = value.ToBool()
- case TargetFolderID:
- item.TargetFolderID = value.ToString()
- case TargetLabelIDs:
- item.TargetLabelIDs = value.ToString()
- default:
- log.Debugln("uknown role ", s, index.Row(), index.Column(), role, role == int(core.Qt__EditRole))
- return false
- }
- s.changedEntityRole(index.Row(), index.Row(), role)
- return true
-}
-
-// Dimension of model: number of rows is equivalent to number of items in list
-func (s *FolderStructure) rowCount(parent *core.QModelIndex) int {
- return s.getCount()
-}
-
-func (s *FolderStructure) getCount() int {
- return len(s.entities)
-}
-
-// Returns names of available item properties
-func (s *FolderStructure) roleNames() map[int]*core.QByteArray {
- return s.Roles()
-}
-
-// Clear removes all items in model
-func (s *FolderStructure) Clear() {
- s.BeginResetModel()
- if s.getCount() != 0 {
- s.entities = []*FolderInfo{}
- }
-
- s.GlobalOptions = FolderInfo{
- mailbox: transfer.Mailbox{
- Name: "=",
- },
- FromDate: 0,
- ToDate: 0,
- TargetFolderID: "",
- TargetLabelIDs: "",
- }
- s.EndResetModel()
-}
-
-// Method connected to addEntry slot
-func (s *FolderStructure) addEntry(entry *FolderInfo) {
- s.insertEntry(entry, s.getCount())
-}
-
-// NewUniqId which is not in map yet.
-func (s *FolderStructure) newUniqId() (name string) {
- name = s.GlobalOptions.mailbox.Name
- mbox := transfer.Mailbox{Name: name}
- for newVal := byte(name[0]); true; newVal++ {
- mbox.Name = string([]byte{newVal})
- if s.getRowById(mbox.Hash()) < GlobalOptionIndex {
- return
- }
- }
- return
-}
-
-// Method connected to addEntry slot
-func (s *FolderStructure) insertEntry(entry *FolderInfo, i int) {
- s.BeginInsertRows(core.NewQModelIndex(), i, i)
- s.entities = append(s.entities[:i], append([]*FolderInfo{entry}, s.entities[i:]...)...)
- s.EndInsertRows()
- // update global if conflict
- if entry.mailbox.Hash() == s.GlobalOptions.mailbox.Hash() {
- globalName := s.newUniqId()
- s.GlobalOptions.mailbox.Name = globalName
- }
-}
-
-func (s *FolderStructure) GetInfo(row int) FolderInfo {
- return *s.get(row)
-}
-
-func (s *FolderStructure) changedEntityRole(rowStart int, rowEnd int, roles ...int) {
- if rowStart < GlobalOptionIndex || rowEnd < GlobalOptionIndex {
- return
- }
- if rowStart < 0 || rowStart >= s.getCount() {
- rowStart = 0
- }
- if rowEnd < 0 || rowEnd >= s.getCount() {
- rowEnd = s.getCount()
- }
- if rowStart > rowEnd {
- tmp := rowStart
- rowStart = rowEnd
- rowEnd = tmp
- }
- indexStart := s.Index(rowStart, 0, core.NewQModelIndex())
- indexEnd := s.Index(rowEnd, 0, core.NewQModelIndex())
- s.updateSelection(indexStart, indexEnd, roles)
- s.DataChanged(indexStart, indexEnd, roles)
-}
-
-func (s *FolderStructure) setFolderSelection(id string, toSelect bool) {
- log.Debugf("set folder selection %q %b", id, toSelect)
- i := s.getRowById(id)
- //
- info := s.get(i)
- before := info.IsFolderSelected
- info.IsFolderSelected = toSelect
- if err := s.saveRule(info); err != nil {
- s.get(i).IsFolderSelected = before
- log.WithError(err).WithField("id", id).WithField("toSelect", toSelect).Error("Cannot set selection")
- return
- }
- //
- s.changedEntityRole(i, i, IsFolderSelected)
-}
-
-func (s *FolderStructure) setTargetFolderID(id, target string) {
- log.Debugf("set targetFolderID %q %q", id, target)
- i := s.getRowById(id)
- //
- info := s.get(i)
- //s.get(i).TargetFolderID = target
- before := info.TargetFolderID
- info.TargetFolderID = target
- if err := s.saveRule(info); err != nil {
- info.TargetFolderID = before
- log.WithError(err).WithField("id", id).WithField("target", target).Error("Cannot set target")
- return
- }
- //
- s.changedEntityRole(i, i, TargetFolderID)
- if target == "" { // do not import
- before := info.TargetLabelIDs
- info.TargetLabelIDs = ""
- if err := s.saveRule(info); err != nil {
- info.TargetLabelIDs = before
- log.WithError(err).WithField("id", id).WithField("target", target).Error("Cannot set target")
- return
- }
- s.changedEntityRole(i, i, TargetLabelIDs)
- }
-}
-
-func (s *FolderStructure) addTargetLabelID(id, label string) {
- log.Debugf("add target label id %q %q", id, label)
- if label == "" {
- return
- }
- i := s.getRowById(id)
- info := s.get(i)
- before := info.TargetLabelIDs
- info.AddTargetLabel(label)
- if err := s.saveRule(info); err != nil {
- info.TargetLabelIDs = before
- log.WithError(err).WithField("id", id).WithField("label", label).Error("Cannot add label")
- return
- }
- s.changedEntityRole(i, i, TargetLabelIDs)
-}
-
-func (s *FolderStructure) removeTargetLabelID(id, label string) {
- log.Debugf("remove label id %q %q", id, label)
- if label == "" {
- return
- }
- i := s.getRowById(id)
- info := s.get(i)
- before := info.TargetLabelIDs
- info.RemoveTargetLabel(label)
- if err := s.saveRule(info); err != nil {
- info.TargetLabelIDs = before
- log.WithError(err).WithField("id", id).WithField("label", label).Error("Cannot remove label")
- return
- }
- s.changedEntityRole(i, i, TargetLabelIDs)
-}
-
-func (s *FolderStructure) setFromToDate(id string, from, to int64) {
- log.Debugf("set from to date %q %d %d", id, from, to)
- i := s.getRowById(id)
- info := s.get(i)
- beforeFrom := info.FromDate
- beforeTo := info.ToDate
- info.FromDate = from
- info.ToDate = to
- if err := s.saveRule(info); err != nil {
- info.FromDate = beforeFrom
- info.ToDate = beforeTo
- log.WithError(err).WithField("id", id).WithField("from", from).WithField("to", to).Error("Cannot set date")
- return
- }
- s.changedEntityRole(i, i, FolderFromDate, FolderToDate)
-}
-
-func (s *FolderStructure) selectType(folderType string, toSelect bool) {
- log.Debugf("set type %q %b", folderType, toSelect)
- iFirst, iLast := -1, -1
- for i, entity := range s.entities {
- if entity.IsType(folderType) {
- if iFirst == -1 {
- iFirst = i
- }
- before := entity.IsFolderSelected
- entity.IsFolderSelected = toSelect
- if err := s.saveRule(entity); err != nil {
- entity.IsFolderSelected = before
- log.WithError(err).WithField("i", i).WithField("type", folderType).WithField("toSelect", toSelect).Error("Cannot select type")
- }
- iLast = i
- }
- }
- if iFirst != -1 {
- s.changedEntityRole(iFirst, iLast, IsFolderSelected)
- }
-}
-
-func (s *FolderStructure) updateSelection(topLeft *core.QModelIndex, bottomRight *core.QModelIndex, roles []int) {
- for _, role := range roles {
- switch role {
- case IsFolderSelected:
- s.SetSelectedFolders(true)
- s.SetSelectedLabels(true)
- s.SetAtLeastOneSelected(false)
- for _, entity := range s.entities {
- if entity.IsFolderSelected {
- s.SetAtLeastOneSelected(true)
- } else {
- if entity.IsType(FolderTypeFolder) {
- s.SetSelectedFolders(false)
- }
- if entity.IsType(FolderTypeLabel) {
- s.SetSelectedLabels(false)
- }
- }
- if !s.IsSelectedFolders() && !s.IsSelectedLabels() && s.IsAtLeastOneSelected() {
- break
- }
- }
- default:
- }
- }
-}
-
-func (s *FolderStructure) hasFolderWithName(name string) bool {
- for _, entity := range s.entities {
- if entity.mailbox.Name == name {
- return true
- }
- }
- return false
-}
-
-func (s *FolderStructure) getRowById(id string) (row int) {
- for row = GlobalOptionIndex; row < s.getCount(); row++ {
- if id == s.get(row).mailbox.Hash() {
- return
- }
- }
- row = GlobalOptionIndex - 1
- return
-}
-
-func (s *FolderStructure) hasTarget() bool {
- for row := 0; row < s.getCount(); row++ {
- if s.get(row).TargetFolderID != "" {
- return true
- }
- }
- return false
-}
-
-// Getter for account info pointer
-// index out of array length returns empty folder info to avoid segfault
-// index == GlobalOptionIndex is set to access global options
-func (s *FolderStructure) get(index int) *FolderInfo {
- if index < GlobalOptionIndex || index >= s.getCount() {
- return &FolderInfo{}
- }
- if index == GlobalOptionIndex {
- return &s.GlobalOptions
- }
- return s.entities[index]
-}
diff --git a/internal/frontend/qt-ie/folder_structure.go b/internal/frontend/qt-ie/folder_structure.go
deleted file mode 100644
index 8f6d18db..00000000
--- a/internal/frontend/qt-ie/folder_structure.go
+++ /dev/null
@@ -1,196 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// +build build_qt
-
-package qtie
-
-// TODO:
-// Proposal for new structure
-// It will be a bit more memory but much better performance
-// * Rules:
-// * rules []Rule /QAbstracItemModel/
-// * globalFromDate int64
-// * globalToDate int64
-// * globalLabel Mbox
-// * targetPath string
-// * filterEncryptedBodies bool
-// * Rule
-// * sourceMbox: Mbox
-// * targetFolders: []Mbox /QAbstracItemModel/ (all available target folders)
-// * targetLabels: []Mbox /QAbstracItemModel/ (all available target labels)
-// * selectedLabelColors: QStringList (need reset context on change) (show label list)
-// * fromDate int64
-// * toDate int64
-// * Mbox
-// * IsActive bool (show checkox)
-// * Name string (show name)
-// * Type string (show icon)
-// * Color string (show icon)
-//
-// Biggest update: add folder or label for all roles update target models
-
-import (
- qtcommon "github.com/ProtonMail/proton-bridge/internal/frontend/qt-common"
- "github.com/ProtonMail/proton-bridge/internal/transfer"
- "github.com/therecipe/qt/core"
-)
-
-// FolderStructure model providing container for items (folder info) to QML
-//
-// QML ListView connects the model from Go and it shows item (entities)
-// information.
-//
-// Copied and edited from `github.com/therecipe/qt/internal/examples/sailfish/listview`
-//
-// NOTE: When implementing a model it is important to remember that QAbstractItemModel does not store any data itself !!!!
-// see https://doc.qt.io/qt-5/model-view-programming.html#designing-a-model
-type FolderStructure struct {
- core.QAbstractListModel
-
- // QtObject Constructor
- _ func() `constructor:"init"`
-
- // List of item properties
- //
- // All available item properties are inside the map
- _ map[int]*core.QByteArray `property:"roles"`
-
- // The data storage
- //
- // The slice with all entities. It is not accessed directly but using
- // `data(index,role)`
- entities []*FolderInfo
- GlobalOptions FolderInfo
-
- transfer *transfer.Transfer
-
- // Global Folders/Labels selection flag, use setter from QML
- _ bool `property:"selectedLabels"`
- _ bool `property:"selectedFolders"`
- _ bool `property:"atLeastOneSelected"`
-
- // Getters (const)
- _ func() int `slot:"getCount"`
- _ func(index int) string `slot:"getID"`
- _ func(id string) string `slot:"getName"`
- _ func(id string) string `slot:"getType"`
- _ func(id string) string `slot:"getColor"`
- _ func(id string) int64 `slot:"getFrom"`
- _ func(id string) int64 `slot:"getTo"`
- _ func(id string) string `slot:"getTargetLabelIDs"`
- _ func(name string) bool `slot:"hasFolderWithName"`
- _ func() bool `slot:"hasTarget"`
-
- // TODO get folders
- // TODO get labels
- // TODO get selected labels
- // TODO get selected folder
-
- // Setters (emits DataChanged)
- _ func(fileType string, toSelect bool) `slot:"selectType"`
- _ func(id string, toSelect bool) `slot:"setFolderSelection"`
- _ func(id string, target string) `slot:"setTargetFolderID"`
- _ func(id string, label string) `slot:"addTargetLabelID"`
- _ func(id string, label string) `slot:"removeTargetLabelID"`
- _ func(id string, from, to int64) `slot:"setFromToDate"`
-}
-
-// FolderInfo is the element of model
-//
-// It contains all data for one structure entry
-type FolderInfo struct {
- /*
- FolderId string
- FolderFullPath string
- FolderColor string
- FolderFullName string
- */
- mailbox transfer.Mailbox // TODO how to reference from qml source mailbox to go target mailbox
- FolderType string
- FolderEntries int // todo remove
- IsFolderSelected bool
- FromDate int64 // Unix seconds
- ToDate int64 // Unix seconds
- TargetFolderID string // target ID TODO: this will be hash
- TargetLabelIDs string // semicolon separated list of label ID same here
-}
-
-// Registration of new metatype before creating instance
-//
-// NOTE: check it is run once per program. write a log
-func init() {
- FolderStructure_QRegisterMetaType()
-}
-
-// Constructor
-//
-// Creates the map for item properties and connects the methods
-func (s *FolderStructure) init() {
- s.SetRoles(map[int]*core.QByteArray{
- FolderId: qtcommon.NewQByteArrayFromString("folderId"),
- FolderName: qtcommon.NewQByteArrayFromString("folderName"),
- FolderColor: qtcommon.NewQByteArrayFromString("folderColor"),
- FolderType: qtcommon.NewQByteArrayFromString("folderType"),
- FolderEntries: qtcommon.NewQByteArrayFromString("folderEntries"),
- IsFolderSelected: qtcommon.NewQByteArrayFromString("isFolderSelected"),
- FolderFromDate: qtcommon.NewQByteArrayFromString("fromDate"),
- FolderToDate: qtcommon.NewQByteArrayFromString("toDate"),
- TargetFolderID: qtcommon.NewQByteArrayFromString("targetFolderID"),
- TargetLabelIDs: qtcommon.NewQByteArrayFromString("targetLabelIDs"),
- })
-
- // basic QAbstractListModel mehods
- s.ConnectGetCount(s.getCount)
- s.ConnectRowCount(s.rowCount)
- s.ConnectColumnCount(func(parent *core.QModelIndex) int { return 1 }) // for list it should be always 1
- s.ConnectData(s.data)
- s.ConnectHeaderData(s.headerData)
- s.ConnectRoleNames(s.roleNames)
- // Editable QAbstractListModel needs: https://doc.qt.io/qt-5/model-view-programming.html#an-editable-model
- s.ConnectSetData(s.setData)
- s.ConnectFlags(s.flags)
-
- // Custom FolderStructure slots to export
-
- // Getters (const)
- s.ConnectGetID(func(row int) string { return s.get(row).mailbox.Hash() })
- s.ConnectGetType(func(id string) string { row := s.getRowById(id); return s.get(row).FolderType })
- s.ConnectGetName(func(id string) string { row := s.getRowById(id); return s.get(row).mailbox.Name })
- s.ConnectGetColor(func(id string) string { row := s.getRowById(id); return s.get(row).mailbox.Color })
- s.ConnectGetFrom(func(id string) int64 { row := s.getRowById(id); return s.get(row).FromDate })
- s.ConnectGetTo(func(id string) int64 { row := s.getRowById(id); return s.get(row).ToDate })
- s.ConnectGetTargetLabelIDs(func(id string) string { row := s.getRowById(id); return s.get(row).TargetLabelIDs })
- s.ConnectHasFolderWithName(s.hasFolderWithName)
- s.ConnectHasTarget(s.hasTarget)
-
- // Setters (emits DataChanged)
- s.ConnectSelectType(s.selectType)
- s.ConnectSetFolderSelection(s.setFolderSelection)
- s.ConnectSetTargetFolderID(s.setTargetFolderID)
- s.ConnectAddTargetLabelID(s.addTargetLabelID)
- s.ConnectRemoveTargetLabelID(s.removeTargetLabelID)
- s.ConnectSetFromToDate(s.setFromToDate)
-
- s.GlobalOptions = FolderInfo{
- mailbox: transfer.Mailbox{Name: "="},
- FromDate: 0,
- ToDate: 0,
- TargetFolderID: "",
- TargetLabelIDs: "",
- }
-}
diff --git a/internal/frontend/qt-ie/folder_structure_test.go b/internal/frontend/qt-ie/folder_structure_test.go
deleted file mode 100644
index 5ffbdbdd..00000000
--- a/internal/frontend/qt-ie/folder_structure_test.go
+++ /dev/null
@@ -1,65 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// +build build_qt
-
-package qtie
-
-import (
- "testing"
-)
-
-func hasNumberOfLabels(tb testing.TB, folder *FolderInfo, expected int) {
- if current := len(folder.TargetLabelIDList()); current != expected {
- tb.Error("Folder has wrong number of labels. Expected", expected, "has", current, " labels", folder.TargetLabelIDs)
- }
-}
-
-func labelStringEquals(tb testing.TB, folder *FolderInfo, expected string) {
- if current := folder.TargetLabelIDs; current != expected {
- tb.Error("Folder returned wrong labels. Expected", expected, "has", current, " labels", folder.TargetLabelIDs)
- }
-}
-
-func TestLabelInfoUniqSet(t *testing.T) {
- folder := &FolderInfo{}
- labelStringEquals(t, folder, "")
- hasNumberOfLabels(t, folder, 0)
- // add label
- folder.AddTargetLabel("blah")
- hasNumberOfLabels(t, folder, 1)
- labelStringEquals(t, folder, "blah")
- //
- folder.AddTargetLabel("blah___")
- hasNumberOfLabels(t, folder, 2)
- labelStringEquals(t, folder, "blah;blah___")
- // add same label
- folder.AddTargetLabel("blah")
- hasNumberOfLabels(t, folder, 2)
- // remove label
- folder.RemoveTargetLabel("blah")
- hasNumberOfLabels(t, folder, 1)
- //
- folder.AddTargetLabel("blah___")
- hasNumberOfLabels(t, folder, 1)
- // remove same label
- folder.RemoveTargetLabel("blah")
- hasNumberOfLabels(t, folder, 1)
- // add again label
- folder.AddTargetLabel("blah")
- hasNumberOfLabels(t, folder, 2)
-}
diff --git a/internal/frontend/qt-ie/frontend.go b/internal/frontend/qt-ie/frontend.go
deleted file mode 100644
index f63753b8..00000000
--- a/internal/frontend/qt-ie/frontend.go
+++ /dev/null
@@ -1,557 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// +build build_qt
-
-package qtie
-
-import (
- "errors"
- "os"
- "sync"
-
- "github.com/ProtonMail/proton-bridge/internal/config/settings"
- "github.com/ProtonMail/proton-bridge/internal/events"
- qtcommon "github.com/ProtonMail/proton-bridge/internal/frontend/qt-common"
- "github.com/ProtonMail/proton-bridge/internal/frontend/types"
- "github.com/ProtonMail/proton-bridge/internal/importexport"
- "github.com/ProtonMail/proton-bridge/internal/locations"
- "github.com/ProtonMail/proton-bridge/internal/transfer"
- "github.com/ProtonMail/proton-bridge/internal/updater"
- "github.com/ProtonMail/proton-bridge/pkg/listener"
-
- "github.com/therecipe/qt/core"
- "github.com/therecipe/qt/gui"
- "github.com/therecipe/qt/qml"
- "github.com/therecipe/qt/widgets"
-
- "github.com/sirupsen/logrus"
- "github.com/skratchdot/open-golang/open"
-)
-
-var log = logrus.WithField("pkg", "frontend-qt-ie")
-
-// FrontendQt is API between Import-Export and Qt
-//
-// With this interface it is possible to control Qt-Gui interface using pointers to
-// Qt and QML objects. QML signals and slots are connected via methods of GoQMLInterface.
-type FrontendQt struct {
- panicHandler types.PanicHandler
- locations *locations.Locations
- settings *settings.Settings
- eventListener listener.Listener
- updater types.Updater
- ie types.ImportExporter
-
- App *widgets.QApplication // Main Application pointer
- View *qml.QQmlApplicationEngine // QML engine pointer
- MainWin *core.QObject // Pointer to main window inside QML
- Qml *GoQMLInterface // Object accessible from both Go and QML for methods and signals
- Accounts qtcommon.Accounts // Providing data for accounts ListView
-
- programName string // App name
- programVersion string // Program version
- buildVersion string // Program build version
-
- TransferRules *TransferRules
- ErrorList *ErrorListModel // Providing data for error reporting
-
- transfer *transfer.Transfer
- progress *transfer.Progress
-
- restarter types.Restarter
-
- // saving most up-to-date update info to install it manually
- updateInfo updater.VersionInfo
-
- initializing sync.WaitGroup
- initializationDone sync.Once
-}
-
-// New is constructor for Import-Export Qt-Go interface
-func New(
- version, buildVersion, programName string,
- panicHandler types.PanicHandler,
- locations *locations.Locations,
- settings *settings.Settings,
- eventListener listener.Listener,
- updater types.Updater,
- ie types.ImportExporter,
- restarter types.Restarter,
-) *FrontendQt {
- f := &FrontendQt{
- panicHandler: panicHandler,
- locations: locations,
- settings: settings,
- programName: programName,
- programVersion: "v" + version,
- eventListener: eventListener,
- updater: updater,
- buildVersion: buildVersion,
- ie: ie,
- restarter: restarter,
- }
-
- // Initializing.Done is only called sync.Once. Please keep the increment
- // set to 1
- f.initializing.Add(1)
-
- log.Debugf("New Qt frontend: %p", f)
- return f
-}
-
-// Loop function for Import-Export interface. It runs QtExecute in main thread
-// with no additional function.
-func (f *FrontendQt) Loop() (err error) {
- err = f.QtExecute(func(f *FrontendQt) error { return nil })
- return err
-}
-
-func (f *FrontendQt) NotifyManualUpdate(update updater.VersionInfo, canInstall bool) {
- f.SetVersion(update)
- f.Qml.SetUpdateCanInstall(canInstall)
- f.Qml.NotifyManualUpdate()
-}
-
-func (f *FrontendQt) SetVersion(version updater.VersionInfo) {
- f.Qml.SetUpdateVersion(version.Version.String())
- f.Qml.SetUpdateLandingPage(version.LandingPage)
- f.Qml.SetUpdateReleaseNotesLink(version.ReleaseNotesPage)
- f.updateInfo = version
-}
-
-func (f *FrontendQt) NotifySilentUpdateInstalled() {
- //f.Qml.NotifySilentUpdateRestartNeeded()
-}
-
-func (f *FrontendQt) NotifySilentUpdateError(err error) {
- //f.Qml.NotifySilentUpdateError()
-}
-
-func (f *FrontendQt) watchEvents() {
- credentialsErrorCh := f.eventListener.ProvideChannel(events.CredentialsErrorEvent)
- internetOffCh := f.eventListener.ProvideChannel(events.InternetOffEvent)
- internetOnCh := f.eventListener.ProvideChannel(events.InternetOnEvent)
- secondInstanceCh := f.eventListener.ProvideChannel(events.SecondInstanceEvent)
- restartBridgeCh := f.eventListener.ProvideChannel(events.RestartBridgeEvent)
- addressChangedCh := f.eventListener.ProvideChannel(events.AddressChangedEvent)
- addressChangedLogoutCh := f.eventListener.ProvideChannel(events.AddressChangedLogoutEvent)
- logoutCh := f.eventListener.ProvideChannel(events.LogoutEvent)
- updateApplicationCh := f.eventListener.ProvideChannel(events.UpgradeApplicationEvent)
- newUserCh := f.eventListener.ProvideChannel(events.UserRefreshEvent)
- for {
- select {
- case <-credentialsErrorCh:
- f.Qml.NotifyHasNoKeychain()
- case <-internetOffCh:
- f.Qml.SetConnectionStatus(false)
- case <-internetOnCh:
- f.Qml.SetConnectionStatus(true)
- case <-secondInstanceCh:
- f.Qml.ShowWindow()
- case <-restartBridgeCh:
- f.restarter.SetToRestart()
- f.App.Quit()
- case address := <-addressChangedCh:
- f.Qml.NotifyAddressChanged(address)
- case address := <-addressChangedLogoutCh:
- f.Qml.NotifyAddressChangedLogout(address)
- case userID := <-logoutCh:
- user, err := f.ie.GetUser(userID)
- if err != nil {
- return
- }
- f.Qml.NotifyLogout(user.Username())
- case <-updateApplicationCh:
- f.Qml.ProcessFinished()
- f.Qml.NotifyForceUpdate()
- case <-newUserCh:
- f.Qml.LoadAccounts()
- }
- }
-}
-
-func (f *FrontendQt) qtSetupQmlAndStructures() {
- f.App = widgets.NewQApplication(len(os.Args), os.Args)
- // view
- f.View = qml.NewQQmlApplicationEngine(f.App)
- // Add Go-QML Import-Export
- f.Qml = NewGoQMLInterface(nil)
- f.Qml.SetFrontend(f) // provides access
- f.View.RootContext().SetContextProperty("go", f.Qml)
-
- // Add AccountsModel
- f.Accounts.SetupAccounts(f.Qml, f.ie, f.restarter)
- f.View.RootContext().SetContextProperty("accountsModel", f.Accounts.Model)
-
- // Add TransferRules structure
- f.TransferRules = NewTransferRules(nil)
- f.View.RootContext().SetContextProperty("transferRules", f.TransferRules)
-
- // Add error list modal
- f.ErrorList = NewErrorListModel(nil)
- f.View.RootContext().SetContextProperty("errorList", f.ErrorList)
- f.Qml.ConnectLoadImportReports(f.ErrorList.load)
-
- // Import path and load QML files
- f.View.AddImportPath("qrc:///")
- f.View.Load(core.NewQUrl3("qrc:/uiie.qml", 0))
-
- // TODO set the first start flag
- //log.Error("Get FirstStart: Not implemented")
- //if prefs.Get(prefs.FirstStart) == "true" {
- if false {
- f.Qml.SetIsFirstStart(true)
- } else {
- f.Qml.SetIsFirstStart(false)
- }
-}
-
-// QtExecute in main for starting Qt application
-//
-// It is needed to have just one Qt application per program (at least per same
-// thread). This functions reads the main user interface defined in QML files.
-// The files are appended to library by Qt-QRC.
-func (f *FrontendQt) QtExecute(Procedure func(*FrontendQt) error) error {
- qtcommon.QtSetupCoreAndControls(f.programName, f.programVersion)
- f.qtSetupQmlAndStructures()
- // Check QML is loaded properly
- if len(f.View.RootObjects()) == 0 {
- //return errors.New(errors.ErrQApplication, "QML not loaded properly")
- return errors.New("QML not loaded properly")
- }
- // Obtain main window (need for invoke method)
- f.MainWin = f.View.RootObjects()[0]
- // Injected procedure for out-of-main-thread applications
- if err := Procedure(f); err != nil {
- return err
- }
-
- // List of used packages
- f.Qml.SetCredits(importexport.Credits)
- f.Qml.SetFullversion(f.buildVersion)
-
- //if f.settings.GetBool(settings.AutoUpdateKey) {
- // f.Qml.SetIsAutoUpdate(true)
- //} else {
- // f.Qml.SetIsAutoUpdate(false)
- //}
-
- go func() {
- defer f.panicHandler.HandlePanic()
- f.watchEvents()
- }()
-
- // Loop
- if ret := gui.QGuiApplication_Exec(); ret != 0 {
- //err := errors.New(errors.ErrQApplication, "Event loop ended with return value: %v", string(ret))
- err := errors.New("Event loop ended with return value: " + string(ret))
- log.Warnln("QGuiApplication_Exec: ", err)
- return err
- }
- log.Debug("Closing...")
- //prefs.Set(prefs.FirstStart, "false")
- return nil
-}
-
-func (f *FrontendQt) openLogs() {
- logsPath, err := f.locations.ProvideLogsPath()
- if err != nil {
- return
- }
-
- go open.Run(logsPath)
-}
-
-func (f *FrontendQt) openReport() {
- go open.Run(f.Qml.ImportLogFileName())
-}
-
-func (f *FrontendQt) openDownloadLink() {
- // NOTE: Fix this.
-}
-
-// sendImportReport sends an anonymized import or export report file to our customer support
-func (f *FrontendQt) sendImportReport(address string) bool { // Todo_: Rename to sendReport?
- var accname = "No account logged in"
- if f.Accounts.Model.Count() > 0 {
- accname = f.Accounts.Model.Get(0).Account()
- }
-
- if f.progress == nil {
- log.Errorln("Failed to send process report: Missing progress")
- return false
- }
-
- report := f.progress.GenerateBugReport()
-
- if err := f.ie.ReportFile(
- core.QSysInfo_ProductType(),
- core.QSysInfo_PrettyProductName(),
- accname,
- address,
- report,
- ); err != nil {
- log.Errorln("Failed to send process report:", err)
- return false
- }
-
- log.Info("Report send successfully")
- return true
-}
-
-// sendBug sends a bug report described by user to our customer support
-func (f *FrontendQt) sendBug(description, emailClient, address string) bool {
- var accname = "No account logged in"
- if f.Accounts.Model.Count() > 0 {
- accname = f.Accounts.Model.Get(0).Account()
- }
- if accname == "" {
- accname = "Unknown account"
- }
-
- if err := f.ie.ReportBug(
- core.QSysInfo_ProductType(),
- core.QSysInfo_PrettyProductName(),
- description,
- accname,
- address,
- emailClient,
- ); err != nil {
- log.Errorln("while sendBug:", err)
- return false
- }
-
- return true
-}
-
-//func (f *FrontendQt) toggleAutoUpdate() {
-// defer f.Qml.ProcessFinished()
-//
-// if f.settings.GetBool(settings.AutoUpdateKey) {
-// f.settings.SetBool(settings.AutoUpdateKey, false)
-// f.Qml.SetIsAutoUpdate(false)
-// } else {
-// f.settings.SetBool(settings.AutoUpdateKey, true)
-// f.Qml.SetIsAutoUpdate(true)
-// }
-//}
-
-func (f *FrontendQt) showError(code int, err error) {
- f.Qml.SetErrorDescription(err.Error())
- log.WithField("code", code).Errorln(err.Error())
- f.Qml.NotifyError(code)
-}
-
-func (f *FrontendQt) emitEvent(evType, msg string) {
- f.eventListener.Emit(evType, msg)
-}
-
-func (f *FrontendQt) setProgressManager(progress *transfer.Progress) {
- f.progress = progress
- f.ErrorList.Progress = progress
-
- f.Qml.ConnectPauseProcess(func() { progress.Pause("paused") })
- f.Qml.ConnectResumeProcess(progress.Resume)
- f.Qml.ConnectCancelProcess(func() {
- progress.Stop()
- })
- f.Qml.SetProgress(0)
-
- go func() {
- log.Trace("Start reading updates")
- defer func() {
- log.Trace("Finishing reading updates")
- f.Qml.DisconnectPauseProcess()
- f.Qml.DisconnectResumeProcess()
- f.Qml.DisconnectCancelProcess()
- f.Qml.SetProgress(1)
- f.progress = nil
- }()
-
- updates := progress.GetUpdateChannel()
- for range updates {
- if progress.IsStopped() {
- break
- }
- counts := progress.GetCounts()
- f.Qml.SetTotal(int(counts.Total))
- f.Qml.SetProgressImported(int(counts.Imported))
- f.Qml.SetProgressSkipped(int(counts.Skipped))
- f.Qml.SetProgressFails(int(counts.Failed))
- f.Qml.SetProgressDescription(progress.PauseReason())
- if counts.Total > 0 {
- newProgress := counts.Progress()
- if newProgress >= 0 && newProgress != f.Qml.Progress() {
- f.Qml.SetProgress(newProgress)
- f.Qml.ProgressChanged(newProgress)
- }
- }
- }
- // Counts will add lost messages only once the progress is completeled.
- counts := progress.GetCounts()
- f.Qml.SetProgressImported(int(counts.Imported))
- f.Qml.SetProgressSkipped(int(counts.Skipped))
- f.Qml.SetProgressFails(int(counts.Failed))
-
- if err := progress.GetFatalError(); err != nil {
- f.Qml.SetProgressDescription(err.Error())
- } else {
- f.Qml.SetProgressDescription("")
- }
- }()
-}
-
-func (f *FrontendQt) startManualUpdate() {
- go func() {
- err := f.updater.InstallUpdate(f.updateInfo)
-
- if err != nil {
- logrus.WithError(err).Error("An error occurred while installing updates manually")
- f.Qml.NotifyManualUpdateError()
- } else {
- f.Qml.NotifyManualUpdateRestartNeeded()
- }
- }()
-}
-
-func (f *FrontendQt) checkIsLatestVersionAndUpdate() bool {
- version, err := f.updater.Check()
-
- if err != nil {
- logrus.WithError(err).Error("An error occurred while checking updates manually")
- f.Qml.NotifyManualUpdateError()
- return false
- }
-
- f.SetVersion(version)
-
- if !f.updater.IsUpdateApplicable(version) {
- logrus.Debug("No need to update")
- return true
- }
-
- logrus.WithField("version", version.Version).Info("An update is available")
-
- if !f.updater.CanInstall(version) {
- logrus.Debug("A manual update is required")
- f.NotifyManualUpdate(version, false)
- return false
- }
-
- f.NotifyManualUpdate(version, true)
- return false
-}
-
-func (s *FrontendQt) checkAndOpenReleaseNotes() {
- go func() {
- _ = s.checkIsLatestVersionAndUpdate()
- s.Qml.OpenReleaseNotesExternally()
- }()
-}
-
-func (s *FrontendQt) checkForUpdates() {
- go func() {
- if s.checkIsLatestVersionAndUpdate() {
- s.Qml.NotifyVersionIsTheLatest()
- }
- }()
-}
-
-func (f *FrontendQt) resetSource() {
- if f.transfer != nil {
- f.transfer.ResetRules()
- if err := f.loadStructuresForImport(); err != nil {
- log.WithError(err).Error("Cannot reload structures after reseting rules.")
- }
- }
-}
-
-func (f *FrontendQt) openLicenseFile() {
- go open.Run(f.locations.GetLicenseFilePath())
-}
-
-// getLocalVersionInfo is identical to bridge.
-func (f *FrontendQt) getLocalVersionInfo() {
- // NOTE: Fix this.
-}
-
-// LeastUsedColor is intended to return color for creating a new inbox or label.
-func (f *FrontendQt) leastUsedColor() string {
- if f.transfer == nil {
- log.Warnln("Getting least used color before transfer exist.")
- return "#7272a7"
- }
-
- m, err := f.transfer.TargetMailboxes()
-
- if err != nil {
- log.Errorln("Getting least used color:", err)
- f.showError(errUnknownError, err)
- }
-
- return transfer.LeastUsedColor(m)
-}
-
-// createLabelOrFolder performs an IE target mailbox creation.
-func (f *FrontendQt) createLabelOrFolder(email, name, color string, isLabel bool, sourceID string) bool {
- // Prepare new mailbox.
- m := transfer.Mailbox{
- Name: name,
- Color: color,
- IsExclusive: !isLabel,
- }
-
- // Select least used color if no color given.
- if m.Color == "" {
- m.Color = f.leastUsedColor()
- }
-
- f.TransferRules.BeginResetModel()
- defer f.TransferRules.EndResetModel()
-
- // Create mailbox.
- m, err := f.transfer.CreateTargetMailbox(m)
- if err != nil {
- log.Errorln("Folder/Label creating:", err)
- err = errors.New(name + "\n" + err.Error()) // GUI splits by \n.
- if isLabel {
- f.showError(errCreateLabelFailed, err)
- } else {
- f.showError(errCreateFolderFailed, err)
- }
- return false
- }
-
- if sourceID == "-1" {
- f.transfer.SetGlobalMailbox(&m)
- } else {
- f.TransferRules.addTargetID(sourceID, m.Hash())
- }
- return true
-}
-
-func (f *FrontendQt) WaitUntilFrontendIsReady() {
- f.initializing.Wait()
-}
-
-// setGUIIsReady unlocks the WaitUntilFrontendIsReady.
-func (f *FrontendQt) setGUIIsReady() {
- f.initializationDone.Do(func() {
- f.initializing.Done()
- })
-}
diff --git a/internal/frontend/qt-ie/frontend_nogui.go b/internal/frontend/qt-ie/frontend_nogui.go
deleted file mode 100644
index b70a1583..00000000
--- a/internal/frontend/qt-ie/frontend_nogui.go
+++ /dev/null
@@ -1,73 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// +build !build_qt
-
-package qtie
-
-import (
- "fmt"
- "net/http"
-
- "github.com/ProtonMail/proton-bridge/internal/config/settings"
- "github.com/ProtonMail/proton-bridge/internal/frontend/types"
- "github.com/ProtonMail/proton-bridge/internal/locations"
- "github.com/ProtonMail/proton-bridge/internal/updater"
- "github.com/ProtonMail/proton-bridge/pkg/listener"
- "github.com/sirupsen/logrus"
-)
-
-var log = logrus.WithField("pkg", "frontend-nogui") //nolint[gochecknoglobals]
-
-type FrontendHeadless struct{}
-
-func (s *FrontendHeadless) Loop() error {
- log.Info("Check status on localhost:8082")
- http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
- fmt.Fprintf(w, "IE is running")
- })
- return http.ListenAndServe(":8082", nil)
-}
-
-func (s *FrontendHeadless) NotifyManualUpdate(update updater.VersionInfo, canInstall bool) {
- // NOTE: Save the update somewhere so that it can be installed when user chooses "install now".
-}
-
-func (s *FrontendHeadless) SetVersion(update updater.VersionInfo) {
-}
-
-func (s *FrontendHeadless) WaitUntilFrontendIsReady() {
-}
-
-func (s *FrontendHeadless) NotifySilentUpdateInstalled() {
-}
-
-func (s *FrontendHeadless) NotifySilentUpdateError(err error) {
-}
-
-func New(
- version, buildVersion, appName string,
- panicHandler types.PanicHandler,
- locations *locations.Locations,
- settings *settings.Settings,
- eventListener listener.Listener,
- updater types.Updater,
- ie types.ImportExporter,
- restarter types.Restarter,
-) *FrontendHeadless {
- return &FrontendHeadless{}
-}
diff --git a/internal/frontend/qt-ie/import.go b/internal/frontend/qt-ie/import.go
deleted file mode 100644
index c36b376e..00000000
--- a/internal/frontend/qt-ie/import.go
+++ /dev/null
@@ -1,92 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// +build build_qt
-
-package qtie
-
-import (
- "github.com/pkg/errors"
-
- "github.com/ProtonMail/proton-bridge/internal/transfer"
-)
-
-// wrapper for QML
-func (f *FrontendQt) setupAndLoadForImport(isFromIMAP bool, sourcePath, sourceEmail, sourcePassword, sourceServer, sourcePort, targetUsername, targetAddress string) {
- errCode := errUnknownError
- var err error
- defer func() {
- if err != nil {
- f.showError(errCode, err)
- f.Qml.ImportStructuresLoadFinished(false)
- } else {
- f.Qml.ImportStructuresLoadFinished(true)
- }
- }()
-
- if isFromIMAP {
- f.transfer, err = f.ie.GetRemoteImporter(targetUsername, targetAddress, sourceEmail, sourcePassword, sourceServer, sourcePort)
- if err != nil {
- switch {
- case errors.Is(err, &transfer.ErrIMAPConnection{}):
- errCode = errWrongServerPathOrPort
- case errors.Is(err, &transfer.ErrIMAPAuth{}):
- errCode = errWrongLoginOrPassword
- case errors.Is(err, &transfer.ErrIMAPAuthMethod{}):
- errCode = errWrongAuthMethod
- default:
- errCode = errRemoteSourceLoadFailed
- }
- return
- }
- } else {
- f.transfer, err = f.ie.GetLocalImporter(targetUsername, targetAddress, sourcePath)
- if err != nil {
- // The only error can be problem to load PM user and address.
- errCode = errPMLoadFailed
- return
- }
- }
-
- if err := f.loadStructuresForImport(); err != nil {
- return
- }
-}
-
-func (f *FrontendQt) loadStructuresForImport() error {
- f.TransferRules.setTransfer(f.transfer)
-
- return nil
-}
-
-func (f *FrontendQt) StartImport(email string, importEncrypted bool) { // TODO email not needed
- log.Trace("Starting import")
-
- f.Qml.SetProgressDescription("init") // TODO use const
- f.Qml.SetProgressImported(0)
- f.Qml.SetProgressSkipped(0)
- f.Qml.SetProgressFails(0)
- f.Qml.SetProgress(0.0)
- f.Qml.SetTotal(1)
- f.Qml.SetImportLogFileName("")
-
- f.transfer.SetSkipEncryptedMessages(!importEncrypted)
- progress := f.transfer.Start()
-
- f.Qml.SetImportLogFileName(progress.FileReport())
- f.setProgressManager(progress)
-}
diff --git a/internal/frontend/qt-ie/mbox.go b/internal/frontend/qt-ie/mbox.go
deleted file mode 100644
index 89aadba4..00000000
--- a/internal/frontend/qt-ie/mbox.go
+++ /dev/null
@@ -1,185 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// +build build_qt
-
-package qtie
-
-import (
- qtcommon "github.com/ProtonMail/proton-bridge/internal/frontend/qt-common"
- "github.com/ProtonMail/proton-bridge/internal/transfer"
- "github.com/sirupsen/logrus"
- "github.com/therecipe/qt/core"
-)
-
-// MboxList is an interface between QML and targets for given rule.
-type MboxList struct {
- core.QAbstractListModel
-
- containsFolders bool // Provides only folders if true. On the other hand provides only labels if false
- transfer *transfer.Transfer
- rule *transfer.Rule
- log *logrus.Entry
-
- _ int `property:"selectedIndex"`
-
- _ func() `constructor:"init"`
-}
-
-func init() {
- // This is needed so the type exists in QML files.
- MboxList_QRegisterMetaType()
-}
-
-func newMboxList(t *TransferRules, rule *transfer.Rule, containsFolders bool) *MboxList {
- m := NewMboxList(t)
- m.BeginResetModel()
- m.transfer = t.transfer
- m.rule = rule
- m.containsFolders = containsFolders
- m.log = log.
- WithField("rule", m.rule.SourceMailbox.Hash()).
- WithField("folders", m.containsFolders)
- m.updateSelectedIndex()
- m.EndResetModel()
- return m
-}
-
-func (m *MboxList) init() {
- m.ConnectRowCount(m.rowCount)
- m.ConnectRoleNames(m.roleNames)
- m.ConnectData(m.data)
-}
-
-func (m *MboxList) rowCount(index *core.QModelIndex) int {
- return len(m.targetMailboxes())
-}
-
-func (m *MboxList) roleNames() map[int]*core.QByteArray {
- return map[int]*core.QByteArray{
- MboxIsActive: qtcommon.NewQByteArrayFromString("isActive"),
- MboxID: qtcommon.NewQByteArrayFromString("mboxID"),
- MboxName: qtcommon.NewQByteArrayFromString("name"),
- MboxType: qtcommon.NewQByteArrayFromString("type"),
- MboxColor: qtcommon.NewQByteArrayFromString("iconColor"),
- }
-}
-
-func (m *MboxList) data(index *core.QModelIndex, role int) *core.QVariant {
- allTargets := m.targetMailboxes()
-
- i := index.Row()
- log := m.log.WithField("row", i).WithField("role", role)
- log.Trace("Mbox data")
-
- if i >= len(allTargets) {
- log.Warning("Invalid index")
- return core.NewQVariant()
- }
-
- if m.transfer == nil {
- log.Warning("Requested mbox list data before transfer is connected")
- return qtcommon.NewQVariantString("")
- }
-
- mbox := allTargets[i]
-
- switch role {
-
- case MboxIsActive:
- for _, selectedMailbox := range m.rule.TargetMailboxes {
- if selectedMailbox.Hash() == mbox.Hash() {
- return qtcommon.NewQVariantBool(true)
- }
- }
- return qtcommon.NewQVariantBool(false)
-
- case MboxID:
- return qtcommon.NewQVariantString(mbox.Hash())
-
- case MboxName, int(core.Qt__DisplayRole):
- return qtcommon.NewQVariantString(mbox.Name)
-
- case MboxType:
- t := "label"
- if mbox.IsExclusive {
- t = "folder"
- }
- return qtcommon.NewQVariantString(t)
-
- case MboxColor:
- return qtcommon.NewQVariantString(mbox.Color)
-
- default:
- log.Error("Requested mbox list data with unknown role")
- return qtcommon.NewQVariantString("")
- }
-}
-
-func (m *MboxList) targetMailboxes() []transfer.Mailbox {
- if m.transfer == nil {
- m.log.Warning("Requested target mailboxes before transfer is connected")
- }
-
- mailboxes, err := m.transfer.TargetMailboxes()
- if err != nil {
- m.log.WithError(err).Error("Unable to get target mailboxes")
- }
-
- return m.filter(mailboxes)
-}
-
-func (m *MboxList) filter(mailboxes []transfer.Mailbox) (filtered []transfer.Mailbox) {
- for _, mailbox := range mailboxes {
- if mailbox.IsExclusive == m.containsFolders {
- filtered = append(filtered, mailbox)
- }
- }
- return
-}
-
-func (m *MboxList) itemsChanged(rule *transfer.Rule) {
- m.rule = rule
- allTargets := m.targetMailboxes()
-
- m.log.WithField("count", len(allTargets)).Trace("Mbox items changed")
-
- m.updateSelectedIndex()
-
- // NOTE: Be careful with indices: If they are invalid the DataChanged
- // signal will not be sent to QML e.g. `end == rowCount - 1`
- if len(allTargets) > 0 {
- begin := m.Index(0, 0, core.NewQModelIndex())
- end := m.Index(len(allTargets)-1, 0, core.NewQModelIndex())
- changedRoles := []int{MboxIsActive}
- m.DataChanged(begin, end, changedRoles)
- }
-}
-
-func (m *MboxList) updateSelectedIndex() {
- allTargets := m.targetMailboxes()
- for index, targetMailbox := range allTargets {
- for _, selectedTarget := range m.rule.TargetMailboxes {
- if targetMailbox.Hash() == selectedTarget.Hash() {
- m.SetSelectedIndex(index)
- return
- }
- }
- }
- m.SetSelectedIndex(-1)
-}
diff --git a/internal/frontend/qt-ie/notification.go b/internal/frontend/qt-ie/notification.go
deleted file mode 100644
index 82b51902..00000000
--- a/internal/frontend/qt-ie/notification.go
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// +build build_qt
-
-package qtie
-
-const (
- TabGlobal = 0
- TabSettings = 1
- TabHelp = 2
- TabQuit = 4
- TabAddAccount = -1
-)
-
-func (s *FrontendQt) SendNotification(tabIndex int, msg string) {
- s.Qml.NotifyBubble(tabIndex, msg)
-}
diff --git a/internal/frontend/qt-ie/path_status.go b/internal/frontend/qt-ie/path_status.go
deleted file mode 100644
index 70084304..00000000
--- a/internal/frontend/qt-ie/path_status.go
+++ /dev/null
@@ -1,83 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// +build build_qt
-
-package qtie
-
-import (
- "io/ioutil"
- "os"
- "path/filepath"
-)
-
-// PathStatus maps folder properties to flag
-type PathStatus int
-
-// Definition of PathStatus flags
-const (
- PathOK PathStatus = 1 << iota
- PathEmptyPath
- PathWrongPath
- PathNotADir
- PathWrongPermissions
- PathDirEmpty
-)
-
-// CheckPathStatus return PathStatus flag as int
-func CheckPathStatus(path string) int {
- stat := PathStatus(0)
- // path is not empty
- if path == "" {
- stat |= PathEmptyPath
- return int(stat)
- }
- // is dir
- fi, err := os.Lstat(path)
- if err != nil {
- stat |= PathWrongPath
- return int(stat)
- }
- if fi.IsDir() {
- // can open
- files, err := ioutil.ReadDir(path)
- if err != nil {
- stat |= PathWrongPermissions
- return int(stat)
- }
- // empty folder
- if len(files) == 0 {
- stat |= PathDirEmpty
- }
- // can write
- tmpFile := filepath.Join(path, "tmp")
- for err == nil {
- tmpFile += "tmp"
- _, err = os.Lstat(tmpFile)
- }
- err = os.Mkdir(tmpFile, 0750)
- if err != nil {
- stat |= PathWrongPermissions
- return int(stat)
- }
- _ = os.Remove(tmpFile)
- } else {
- stat |= PathNotADir
- }
- stat |= PathOK
- return int(stat)
-}
diff --git a/internal/frontend/qt-ie/transfer_rules.go b/internal/frontend/qt-ie/transfer_rules.go
deleted file mode 100644
index 574e6fff..00000000
--- a/internal/frontend/qt-ie/transfer_rules.go
+++ /dev/null
@@ -1,402 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// +build build_qt
-
-package qtie
-
-import (
- qtcommon "github.com/ProtonMail/proton-bridge/internal/frontend/qt-common"
- "github.com/ProtonMail/proton-bridge/internal/transfer"
- "github.com/therecipe/qt/core"
-)
-
-// TransferRules is an interface between QML and transfer.
-type TransferRules struct {
- core.QAbstractListModel
-
- transfer *transfer.Transfer
-
- targetFoldersCache map[string]*MboxList
- targetLabelsCache map[string]*MboxList
-
- _ func() `constructor:"init"`
-
- _ func(sourceID string) *MboxList `slot:"targetFolders,auto"`
- _ func(sourceID string) *MboxList `slot:"targetLabels,auto"`
- _ func(sourceID string, isActive bool) `slot:"setIsRuleActive,auto"`
- _ func(groupName string, isActive bool) `slot:"setIsGroupActive,auto"`
- _ func(sourceID string, fromDate int64, toDate int64) `slot:"setFromToDate,auto"`
- _ func(sourceID string, targetID string) `slot:"addTargetID,auto"`
- _ func(sourceID string, targetID string) `slot:"removeTargetID,auto"`
-
- // globalFromDate and globalToDate is just default value for GUI, always zero.
- _ int `property:"globalFromDate"`
- _ int `property:"globalToDate"`
- _ bool `property:"isLabelGroupSelected"`
- _ bool `property:"isFolderGroupSelected"`
-}
-
-func init() {
- // This is needed so the type exists in QML files.
- TransferRules_QRegisterMetaType()
-}
-
-func (t *TransferRules) init() {
- log.Trace("Initializing transfer rules")
-
- t.targetFoldersCache = make(map[string]*MboxList)
- t.targetLabelsCache = make(map[string]*MboxList)
-
- t.SetGlobalFromDate(0)
- t.SetGlobalToDate(0)
-
- t.ConnectRowCount(t.rowCount)
- t.ConnectRoleNames(t.roleNames)
- t.ConnectData(t.data)
-}
-
-func (t *TransferRules) rowCount(index *core.QModelIndex) int {
- if t.transfer == nil {
- return 0
- }
- return len(t.transfer.GetRules())
-}
-
-func (t *TransferRules) roleNames() map[int]*core.QByteArray {
- return map[int]*core.QByteArray{
- MboxIsActive: qtcommon.NewQByteArrayFromString("isActive"),
- MboxID: qtcommon.NewQByteArrayFromString("mboxID"),
- MboxName: qtcommon.NewQByteArrayFromString("name"),
- MboxType: qtcommon.NewQByteArrayFromString("type"),
- MboxColor: qtcommon.NewQByteArrayFromString("iconColor"),
- RuleTargetLabelColors: qtcommon.NewQByteArrayFromString("labelColors"),
- RuleFromDate: qtcommon.NewQByteArrayFromString("fromDate"),
- RuleToDate: qtcommon.NewQByteArrayFromString("toDate"),
- }
-}
-
-func (t *TransferRules) data(index *core.QModelIndex, role int) *core.QVariant {
- i := index.Row()
- allRules := t.transfer.GetRules()
-
- log := log.WithField("row", i).WithField("role", role)
- log.Trace("Transfer rules data")
-
- if i >= len(allRules) {
- log.Warning("Invalid index")
- return core.NewQVariant()
- }
-
- if t.transfer == nil {
- log.Warning("Requested transfer rules data before transfer is connected")
- return qtcommon.NewQVariantString("")
- }
-
- rule := allRules[i]
-
- switch role {
- case MboxIsActive:
- return qtcommon.NewQVariantBool(rule.Active)
-
- case MboxID:
- return qtcommon.NewQVariantString(rule.SourceMailbox.Hash())
-
- case MboxName:
- return qtcommon.NewQVariantString(rule.SourceMailbox.Name)
-
- case MboxType:
- if rule.SourceMailbox.IsSystemFolder() {
- return qtcommon.NewQVariantString(FolderTypeSystem)
- }
- if rule.SourceMailbox.IsExclusive {
- return qtcommon.NewQVariantString(FolderTypeFolder)
- }
- return qtcommon.NewQVariantString(FolderTypeLabel)
-
- case MboxColor:
- return qtcommon.NewQVariantString(rule.SourceMailbox.Color)
-
- case RuleTargetLabelColors:
- colors := ""
- for _, m := range rule.TargetMailboxes {
- if m.IsExclusive {
- continue
- }
- if colors != "" {
- colors += ";"
- }
- colors += m.Color
- }
- return qtcommon.NewQVariantString(colors)
-
- case RuleFromDate:
- return qtcommon.NewQVariantLong(rule.FromTime)
-
- case RuleToDate:
- return qtcommon.NewQVariantLong(rule.ToTime)
-
- default:
- log.Error("Requested transfer rules data with unknown role")
- return qtcommon.NewQVariantString("")
- }
-}
-
-func (t *TransferRules) setTransfer(transfer *transfer.Transfer) {
- log.Debug("Setting transfer")
- t.BeginResetModel()
- defer t.EndResetModel()
-
- t.transfer = transfer
-
- t.targetFoldersCache = make(map[string]*MboxList)
- t.targetLabelsCache = make(map[string]*MboxList)
-
- t.updateGroupSelection()
-}
-
-// Getters
-
-func (t *TransferRules) targetFolders(sourceID string) *MboxList {
- rule := t.getRule(sourceID)
- if rule == nil {
- return nil
- }
-
- if t.targetFoldersCache[sourceID] == nil {
- log.WithField("source", sourceID).Debug("New target folder")
- t.targetFoldersCache[sourceID] = newMboxList(t, rule, true)
- }
-
- return t.targetFoldersCache[sourceID]
-}
-
-func (t *TransferRules) targetLabels(sourceID string) *MboxList {
- rule := t.getRule(sourceID)
- if rule == nil {
- return nil
- }
-
- if t.targetLabelsCache[sourceID] == nil {
- log.WithField("source", sourceID).Debug("New target label")
- t.targetLabelsCache[sourceID] = newMboxList(t, rule, false)
- }
-
- return t.targetLabelsCache[sourceID]
-}
-
-// Setters
-
-func (t *TransferRules) setIsGroupActive(groupName string, isActive bool) {
- log.WithField("group", groupName).WithField("active", isActive).Trace("Setting group as active/inactive")
-
- wantExclusive := (groupName == FolderTypeFolder)
- for _, rule := range t.transfer.GetRules() {
- if rule.SourceMailbox.IsExclusive != wantExclusive {
- continue
- }
- if rule.SourceMailbox.IsSystemFolder() {
- continue
- }
- if rule.Active != isActive {
- t.setIsRuleActive(rule.SourceMailbox.Hash(), isActive)
- }
- }
-}
-
-func (t *TransferRules) setIsRuleActive(sourceID string, isActive bool) {
- log.WithField("source", sourceID).WithField("active", isActive).Trace("Setting rule as active/inactive")
-
- rule := t.getRule(sourceID)
- if rule == nil {
- return
- }
- if isActive {
- t.setRule(rule.SourceMailbox, rule.TargetMailboxes, rule.FromTime, rule.ToTime, []int{MboxIsActive})
- } else {
- t.unsetRule(rule.SourceMailbox)
- }
-}
-
-func (t *TransferRules) setFromToDate(sourceID string, fromTime int64, toTime int64) {
- log.WithField("source", sourceID).WithField("fromTime", fromTime).WithField("toTime", toTime).Trace("Setting from and to dates")
-
- if sourceID == "-1" {
- t.transfer.SetGlobalTimeLimit(fromTime, toTime)
- return
- }
-
- rule := t.getRule(sourceID)
- if rule == nil {
- return
- }
- t.setRule(rule.SourceMailbox, rule.TargetMailboxes, fromTime, toTime, []int{RuleFromDate, RuleToDate})
-}
-
-func (t *TransferRules) addTargetID(sourceID string, targetID string) {
- log.WithField("source", sourceID).WithField("target", targetID).Trace("Adding target")
-
- rule := t.getRule(sourceID)
- if rule == nil {
- return
- }
- targetMailboxToAdd := t.getMailbox(t.transfer.TargetMailboxes, targetID)
- if targetMailboxToAdd == nil {
- return
- }
-
- newTargetMailboxes := []transfer.Mailbox{}
- found := false
- for _, targetMailbox := range rule.TargetMailboxes {
- if targetMailbox.Hash() == targetMailboxToAdd.Hash() {
- found = true
- }
- if !targetMailboxToAdd.IsExclusive || (targetMailboxToAdd.IsExclusive && !targetMailbox.IsExclusive) {
- newTargetMailboxes = append(newTargetMailboxes, targetMailbox)
- }
- }
- if !found {
- newTargetMailboxes = append(newTargetMailboxes, *targetMailboxToAdd)
- }
- t.setRule(rule.SourceMailbox, newTargetMailboxes, rule.FromTime, rule.ToTime, []int{RuleTargetLabelColors})
- t.updateTargetSelection(sourceID, targetMailboxToAdd.IsExclusive)
-}
-
-func (t *TransferRules) removeTargetID(sourceID string, targetID string) {
- log.WithField("source", sourceID).WithField("target", targetID).Trace("Removing target")
-
- rule := t.getRule(sourceID)
- if rule == nil {
- return
- }
- targetMailboxToRemove := t.getMailbox(t.transfer.TargetMailboxes, targetID)
- if targetMailboxToRemove == nil {
- return
- }
-
- newTargetMailboxes := []transfer.Mailbox{}
- for _, targetMailbox := range rule.TargetMailboxes {
- if targetMailbox.Hash() != targetMailboxToRemove.Hash() {
- newTargetMailboxes = append(newTargetMailboxes, targetMailbox)
- }
- }
- t.setRule(rule.SourceMailbox, newTargetMailboxes, rule.FromTime, rule.ToTime, []int{RuleTargetLabelColors})
- t.updateTargetSelection(sourceID, targetMailboxToRemove.IsExclusive)
-}
-
-// Helpers
-
-// getRule returns rule for given source ID.
-// WARN: Always get new rule after change because previous pointer points to
-// outdated struct with old data.
-func (t *TransferRules) getRule(sourceID string) *transfer.Rule {
- mailbox := t.getMailbox(t.transfer.SourceMailboxes, sourceID)
- if mailbox == nil {
- return nil
- }
- return t.transfer.GetRule(*mailbox)
-}
-
-func (t *TransferRules) getMailbox(mailboxesGetter func() ([]transfer.Mailbox, error), sourceID string) *transfer.Mailbox {
- if t.transfer == nil {
- log.Warn("Getting mailbox without avaiable transfer")
- return nil
- }
-
- mailboxes, err := mailboxesGetter()
- if err != nil {
- log.WithError(err).Error("Failed to get source mailboxes")
- return nil
- }
- for _, mailbox := range mailboxes {
- if mailbox.Hash() == sourceID {
- return &mailbox
- }
- }
- log.WithField("source", sourceID).Error("Mailbox not found for source")
- return nil
-}
-
-func (t *TransferRules) setRule(sourceMailbox transfer.Mailbox, targetMailboxes []transfer.Mailbox, fromTime, toTime int64, changedRoles []int) {
- if err := t.transfer.SetRule(sourceMailbox, targetMailboxes, fromTime, toTime); err != nil {
- log.WithError(err).WithField("source", sourceMailbox.Hash()).Error("Failed to set rule")
- }
- t.ruleChanged(sourceMailbox, changedRoles)
-}
-
-func (t *TransferRules) unsetRule(sourceMailbox transfer.Mailbox) {
- t.transfer.UnsetRule(sourceMailbox)
- t.ruleChanged(sourceMailbox, []int{MboxIsActive})
-}
-
-func (t *TransferRules) ruleChanged(sourceMailbox transfer.Mailbox, changedRoles []int) {
- allRules := t.transfer.GetRules()
- for row, rule := range allRules {
- if rule.SourceMailbox.Hash() != sourceMailbox.Hash() {
- continue
- }
-
- index := t.Index(row, 0, core.NewQModelIndex())
- if !index.IsValid() || row >= len(allRules) {
- log.WithField("row", row).Warning("Invalid index")
- return
- }
-
- log.WithField("row", row).Trace("Transfer rule changed")
- t.DataChanged(index, index, changedRoles)
- break
- }
-
- t.updateGroupSelection()
-}
-
-func (t *TransferRules) updateGroupSelection() {
- areAllLabelsSelected, areAllFoldersSelected := true, true
- for _, rule := range t.transfer.GetRules() {
- if rule.Active {
- continue
- }
- if rule.SourceMailbox.IsSystemFolder() {
- continue
- }
- if rule.SourceMailbox.IsExclusive {
- areAllFoldersSelected = false
- } else {
- areAllLabelsSelected = false
- }
-
- if !areAllLabelsSelected && !areAllFoldersSelected {
- break
- }
- }
-
- t.SetIsLabelGroupSelected(areAllLabelsSelected)
- t.SetIsFolderGroupSelected(areAllFoldersSelected)
-}
-
-func (t *TransferRules) updateTargetSelection(sourceID string, updateFolderSelect bool) {
- rule := t.getRule(sourceID)
- if rule == nil {
- return
- }
-
- if updateFolderSelect {
- t.targetFolders(rule.SourceMailbox.Hash()).itemsChanged(rule)
- } else {
- t.targetLabels(rule.SourceMailbox.Hash()).itemsChanged(rule)
- }
-}
diff --git a/internal/frontend/qt-ie/ui.go b/internal/frontend/qt-ie/ui.go
deleted file mode 100644
index a5fdb0db..00000000
--- a/internal/frontend/qt-ie/ui.go
+++ /dev/null
@@ -1,209 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// +build build_qt
-
-package qtie
-
-import (
- "runtime"
-
- "github.com/therecipe/qt/core"
-)
-
-// GoQMLInterface between go and qml
-//
-// Here we implements all the signals / methods.
-type GoQMLInterface struct {
- core.QObject
-
- _ func() `constructor:"init"`
-
- //_ bool `property:"isAutoUpdate"`
- _ string `property:"currentAddress"`
- _ string `property:"goos"`
- _ string `property:"credits"`
- _ bool `property:"isFirstStart"`
- _ bool `property:"isConnectionOK"`
-
- _ string `property:lastError`
- _ float32 `property:progress`
- _ string `property:progressDescription`
- _ int `property:progressImported`
- _ int `property:progressSkipped`
- _ int `property:progressFails`
- _ int `property:total`
- _ string `property:importLogFileName`
-
- _ string `property:"programTitle"`
- _ string `property:"fullversion"`
- _ string `property:"downloadLink"`
-
- _ string `property:"updateState"`
- _ string `property:"updateVersion"`
- _ bool `property:"updateCanInstall"`
- _ string `property:"updateLandingPage"`
- _ string `property:"updateReleaseNotesLink"`
- _ func() `signal:"notifyManualUpdate"`
- _ func() `signal:"notifyManualUpdateRestartNeeded"`
- _ func() `signal:"notifyManualUpdateError"`
- _ func() `signal:"notifyForceUpdate"`
- //_ func() `signal:"notifySilentUpdateRestartNeeded"`
- //_ func() `signal:"notifySilentUpdateError"`
- _ func() `slot:"checkForUpdates"`
- _ func() `slot:"checkAndOpenReleaseNotes"`
- _ func() `signal:"openReleaseNotesExternally"`
- _ func() `slot:"startManualUpdate"`
- _ func() `slot:"guiIsReady"`
-
- // translations
- _ string `property:"wrongCredentials"`
- _ string `property:"wrongMailboxPassword"`
- _ string `property:"canNotReachAPI"`
- _ string `property:"credentialsNotRemoved"`
- _ string `property:"versionCheckFailed"`
- //
- _ func(isAvailable bool) `signal:"setConnectionStatus"`
-
- _ func() `slot:"setToRestart"`
-
- _ func() `signal:"processFinished"`
- _ func(okay bool) `signal:"exportStructureLoadFinished"`
- _ func(okay bool) `signal:"importStructuresLoadFinished"`
- _ func() `signal:"openManual"`
- _ func(showMessage bool) `signal:"runCheckVersion"`
- _ func() `slot:"openLicenseFile"`
- _ func() `slot:"getLocalVersionInfo"`
- _ func() `slot:"loadImportReports"`
-
- _ func() `signal:"showWindow"`
-
- //_ func() `slot:"toggleAutoUpdate"`
- _ func() `slot:"quit"`
- _ func() `slot:"loadAccounts"`
- _ func() `slot:"openLogs"`
- _ func() `slot:"openDownloadLink"`
- _ func() `slot:"openReport"`
- _ func() `slot:"clearCache"`
- _ func() `slot:"clearKeychain"`
- _ func() `signal:"highlightSystray"`
- _ func() `signal:"normalSystray"`
-
- _ func() string `slot:"getBackendVersion"`
-
- _ func(description, client, address string) bool `slot:"sendBug"`
- _ func(address string) bool `slot:"sendImportReport"`
- _ func(username, address string) `slot:"loadStructureForExport"`
- _ func() string `slot:"leastUsedColor"`
- _ func(username string, name string, color string, isLabel bool, sourceID string) bool `slot:"createLabelOrFolder"`
- _ func(fpath, address, fileType string, attachEncryptedBody bool) `slot:"startExport"`
- _ func(email string, importEncrypted bool) `slot:"startImport"`
- _ func() `slot:"resetSource"`
-
- _ func(isFromIMAP bool, sourcePath, sourceEmail, sourcePassword, sourceServe, sourcePort, targetUsername, targetAddress string) `slot:"setupAndLoadForImport"`
-
- _ string `property:"progressInit"`
-
- _ func(path string) int `slot:"checkPathStatus"`
-
- _ func(evType string, msg string) `signal:"emitEvent"`
- _ func(tabIndex int, message string) `signal:"notifyBubble"`
-
- _ func() `signal:"bubbleClosed"`
- _ func() `signal:"simpleErrorHappen"`
- _ func() `signal:"askErrorHappen"`
- _ func() `signal:"retryErrorHappen"`
- _ func() `signal:"pauseProcess"`
- _ func() `signal:"resumeProcess"`
- _ func() `signal:"cancelProcess"`
-
- _ func(iAccount int, prefRem bool) `slot:"deleteAccount"`
- _ func(iAccount int) `slot:"logoutAccount"`
- _ func(login, password string) int `slot:"login"`
- _ func(twoFacAuth string) int `slot:"auth2FA"`
- _ func(mailboxPassword string) int `slot:"addAccount"`
- _ func(message string, changeIndex int) `signal:"setAddAccountWarning"`
-
- _ func() `signal:"notifyVersionIsTheLatest"`
- _ func() `signal:"notifyKeychainRebuild"`
- _ func() `signal:"notifyHasNoKeychain"`
- _ func(accname string) `signal:"notifyLogout"`
- _ func(accname string) `signal:"notifyAddressChanged"`
- _ func(accname string) `signal:"notifyAddressChangedLogout"`
-
- _ func(hasError bool) `signal:"updateFinished"`
-
- // errors
- _ func() `signal:"answerRetry"`
- _ func(all bool) `signal:"answerSkip"`
- _ func(errCode int) `signal:"notifyError"`
- _ string `property:"errorDescription"`
-}
-
-// Constructor
-func (s *GoQMLInterface) init() {}
-
-// SetFrontend connects all slots and signals from Go to QML
-func (s *GoQMLInterface) SetFrontend(f *FrontendQt) {
- s.ConnectQuit(f.App.Quit)
-
- //s.ConnectToggleAutoUpdate(f.toggleAutoUpdate)
- s.ConnectLoadAccounts(f.Accounts.LoadAccounts)
- s.ConnectOpenLogs(f.openLogs)
- s.ConnectOpenDownloadLink(f.openDownloadLink)
- s.ConnectOpenReport(f.openReport)
- s.ConnectClearCache(f.Accounts.ClearCache)
- s.ConnectClearKeychain(f.Accounts.ClearKeychain)
-
- s.ConnectSendBug(f.sendBug)
- s.ConnectSendImportReport(f.sendImportReport)
-
- s.ConnectDeleteAccount(f.Accounts.DeleteAccount)
- s.ConnectLogoutAccount(f.Accounts.LogoutAccount)
- s.ConnectLogin(f.Accounts.Login)
- s.ConnectAuth2FA(f.Accounts.Auth2FA)
- s.ConnectAddAccount(f.Accounts.AddAccount)
-
- s.SetGoos(runtime.GOOS)
- s.SetProgramTitle(f.programName)
-
- s.ConnectOpenLicenseFile(f.openLicenseFile)
- s.ConnectGetLocalVersionInfo(f.getLocalVersionInfo)
- s.ConnectCheckForUpdates(f.checkForUpdates)
- s.ConnectGetBackendVersion(func() string {
- return f.programVersion
- })
-
- s.ConnectSetToRestart(f.restarter.SetToRestart)
-
- s.ConnectLoadStructureForExport(f.LoadStructureForExport)
- s.ConnectSetupAndLoadForImport(f.setupAndLoadForImport)
- s.ConnectResetSource(f.resetSource)
- s.ConnectLeastUsedColor(f.leastUsedColor)
- s.ConnectCreateLabelOrFolder(f.createLabelOrFolder)
-
- s.ConnectStartExport(f.StartExport)
- s.ConnectStartImport(f.StartImport)
-
- s.ConnectGuiIsReady(f.setGUIIsReady)
-
- s.ConnectCheckPathStatus(CheckPathStatus)
-
- s.ConnectEmitEvent(f.emitEvent)
-
- s.ConnectStartManualUpdate(f.startManualUpdate)
-}
diff --git a/internal/frontend/qt/Makefile.local b/internal/frontend/qt/Makefile.local
deleted file mode 100644
index 826c5907..00000000
--- a/internal/frontend/qt/Makefile.local
+++ /dev/null
@@ -1,64 +0,0 @@
-QMLfiles=$(shell find ../qml/ -name "*.qml") $(shell find ../qml/ -name "qmldir")
-FontAwesome=${CURDIR}/../share/fontawesome-webfont.ttf
-ImageDir=${CURDIR}/../share/icons
-Icons=$(shell find ${ImageDir} -name "*.png")
-
-all: qmlcheck moc.go rcc.cpp logo.ico
-
-deploy:
- qtdeploy build desktop
-
-../qml/ProtonUI/fontawesome.ttf:
- ln -sf ${FontAwesome} $@
-../qml/ProtonUI/images:
- ln -sf ${ImageDir} $@
-
-translate.ts: ${QMLfiles}
- lupdate -recursive qml/ -ts $@
-
-rcc.cpp: ${QMLfiles} ${Icons} resources.qrc
- rm -f rcc.cpp rcc.qrc && qtrcc -o .
-
-
-qmltest:
- qmltestrunner -eventdelay 500 -import ../qml/
-qmlcheck: ../qml/ProtonUI/fontawesome.ttf ../qml/ProtonUI/images
- qmlscene -I ../qml/ -f ../qml/tst_Gui.qml --quit
-qmlpreview: ../qml/ProtonUI/fontawesome.ttf ../qml/ProtonUI/images
- rm -f ../qml/*.qmlc ../qml/BridgeUI/*.qmlc
- qmlscene -verbose -I ../qml/ -f ../qml/tst_Gui.qml
- #qmlscene -qmljsdebugger=port:3768,block -verbose -I ../qml/ -f ../qml/tst_Gui.qml
-
-logo.ico: ../share/icons/logo.ico
- cp $^ $@
-
-
-test: qmlcheck moc.go rcc.cpp
- go test -v -tags=cli
-
-moc.go: ui.go accountModel.go
- qtmoc
-
-distclean: clean
- rm -rf rcc_cgo*.go
-
-clean:
- rm -rf linux/
- rm -rf darwin/
- rm -rf windows/
- rm -rf deploy/
- rm -f logo.ico
- rm -f moc.cpp
- rm -f moc.go
- rm -f moc.h
- rm -f moc_cgo*.go
- rm -f moc_moc.h
- rm -f rcc.cpp
- rm -f rcc.qrc
- rm -f rcc_cgo*.go
- rm -f ../rcc.cpp
- rm -f ../rcc.qrc
- rm -f ../rcc_cgo*.go
- rm -rf ../qml/ProtonUI/images
- rm -f ../qml/ProtonUI/fontawesome.ttf
- find ../qml -name *.qmlc -exec rm {} \;
diff --git a/internal/frontend/qt/accountModel.go b/internal/frontend/qt/accountModel.go
deleted file mode 100644
index 7f99efed..00000000
--- a/internal/frontend/qt/accountModel.go
+++ /dev/null
@@ -1,240 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// +build build_qt
-
-package qt
-
-import (
- "fmt"
-
- "github.com/therecipe/qt/core"
-)
-
-// The element of model.
-// It contains all data for one account and its aliases.
-type AccountInfo struct {
- core.QObject
-
- _ string `property:"account"`
- _ string `property:"userID"`
- _ string `property:"status"`
- _ string `property:"hostname"`
- _ string `property:"password"`
- _ string `property:"security"` // Deprecated, not used.
- _ int `property:"portSMTP"`
- _ int `property:"portIMAP"`
- _ string `property:"aliases"`
- _ bool `property:"isExpanded"`
- _ bool `property:"isCombinedAddressMode"`
-}
-
-// Constants for data map.
-// enum-like constants in Go.
-const (
- Account = int(core.Qt__UserRole) + 1<= len(s.Accounts()) {
- return NewAccountInfo(nil)
- } else {
- return s.Accounts()[index]
- }
-}
-
-// data is a getter for account info data.
-func (s *AccountsModel) data(index *core.QModelIndex, role int) *core.QVariant {
- if !index.IsValid() {
- return core.NewQVariant()
- }
-
- if index.Row() >= len(s.Accounts()) {
- return core.NewQVariant()
- }
-
- var p = s.Accounts()[index.Row()]
-
- switch role {
- case Account:
- return NewQVariantString(p.Account())
- case UserID:
- return NewQVariantString(p.UserID())
- case Status:
- return NewQVariantString(p.Status())
- case Hostname:
- return NewQVariantString(p.Hostname())
- case Password:
- return NewQVariantString(p.Password())
- case Security:
- return NewQVariantString(p.Security())
- case PortIMAP:
- return NewQVariantInt(p.PortIMAP())
- case PortSMTP:
- return NewQVariantInt(p.PortSMTP())
- case Aliases:
- return NewQVariantString(p.Aliases())
- case IsExpanded:
- return NewQVariantBool(p.IsExpanded())
- case IsCombinedAddressMode:
- return NewQVariantBool(p.IsCombinedAddressMode())
- default:
- return core.NewQVariant()
- }
-}
-
-// rowCount returns the dimension of model: number of rows is equivalent to number of items in list.
-func (s *AccountsModel) rowCount(parent *core.QModelIndex) int {
- return len(s.Accounts())
-}
-
-// columnCount returns the dimension of model: AccountsModel has only one column.
-func (s *AccountsModel) columnCount(parent *core.QModelIndex) int {
- return 1
-}
-
-// roleNames returns the names of available item properties.
-func (s *AccountsModel) roleNames() map[int]*core.QByteArray {
- return s.Roles()
-}
-
-// addAccount is connected to the addAccount slot.
-func (s *AccountsModel) addAccount(p *AccountInfo) {
- s.BeginInsertRows(core.NewQModelIndex(), len(s.Accounts()), len(s.Accounts()))
- s.SetAccounts(append(s.Accounts(), p))
- s.SetCount(len(s.Accounts()))
- s.EndInsertRows()
-}
-
-// Method connected to toggleIsAvailable slot.
-func (s *AccountsModel) toggleIsAvailable(row int) {
- var p = s.Accounts()[row]
- currentStatus := p.Status()
- if currentStatus == "active" {
- p.SetStatus("disabled")
- } else if currentStatus == "disabled" {
- p.SetStatus("active")
- } else {
- p.SetStatus("error")
- }
- var pIndex = s.Index(row, 0, core.NewQModelIndex())
- s.DataChanged(pIndex, pIndex, []int{Status})
-}
-
-// Method connected to removeAccount slot.
-func (s *AccountsModel) removeAccount(row int) {
- s.BeginRemoveRows(core.NewQModelIndex(), row, row)
- s.SetAccounts(append(s.Accounts()[:row], s.Accounts()[row+1:]...))
- s.SetCount(len(s.Accounts()))
- s.EndRemoveRows()
-}
-
-// Remove all items in model.
-func (s *AccountsModel) Clear() {
- s.BeginRemoveRows(core.NewQModelIndex(), 0, len(s.Accounts()))
- s.SetAccounts(s.Accounts()[0:0])
- s.SetCount(len(s.Accounts()))
- s.EndRemoveRows()
-}
-
-// Print the content of account models to console.
-func (s *AccountsModel) Dump() {
- fmt.Printf("Dimensions rows %d cols %d\n", s.rowCount(nil), s.columnCount(nil))
- for iAcc := 0; iAcc < s.rowCount(nil); iAcc++ {
- var p = s.Accounts()[iAcc]
- fmt.Printf(" %d. %s\n", iAcc, p.Account())
- }
-}
diff --git a/internal/frontend/qt/accounts.go b/internal/frontend/qt/accounts.go
deleted file mode 100644
index cb0162c0..00000000
--- a/internal/frontend/qt/accounts.go
+++ /dev/null
@@ -1,223 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// +build build_qt
-
-package qt
-
-import (
- "context"
- "fmt"
- "strings"
-
- "github.com/ProtonMail/proton-bridge/internal/bridge"
- "github.com/ProtonMail/proton-bridge/internal/config/settings"
- "github.com/ProtonMail/proton-bridge/internal/events"
- "github.com/ProtonMail/proton-bridge/internal/updater"
- "github.com/ProtonMail/proton-bridge/pkg/keychain"
- pmapi "github.com/ProtonMail/proton-bridge/pkg/pmapi"
-)
-
-func (s *FrontendQt) loadAccounts() {
- accountMutex.Lock()
- defer accountMutex.Unlock()
-
- // Update users.
- s.Accounts.Clear()
-
- users := s.bridge.GetUsers()
-
- // If there are no active accounts.
- if len(users) == 0 {
- log.Info("No active accounts")
- return
- }
- for _, user := range users {
- acc_info := NewAccountInfo(nil)
- username := user.Username()
- if username == "" {
- username = user.ID()
- }
- acc_info.SetAccount(username)
-
- // Set status.
- if user.IsConnected() {
- acc_info.SetStatus("connected")
- } else {
- acc_info.SetStatus("disconnected")
- }
-
- // Set login info.
- acc_info.SetUserID(user.ID())
- acc_info.SetHostname(bridge.Host)
- acc_info.SetPassword(user.GetBridgePassword())
- acc_info.SetPortIMAP(s.settings.GetInt(settings.IMAPPortKey))
- acc_info.SetPortSMTP(s.settings.GetInt(settings.SMTPPortKey))
-
- // Set aliases.
- acc_info.SetAliases(strings.Join(user.GetAddresses(), ";"))
- acc_info.SetIsExpanded(user.ID() == s.userIDAdded)
- acc_info.SetIsCombinedAddressMode(user.IsCombinedAddressMode())
-
- s.Accounts.addAccount(acc_info)
- }
-
- // Updated can clear.
- s.userIDAdded = ""
-}
-
-func (s *FrontendQt) clearCache() {
- defer s.Qml.ProcessFinished()
-
- channel := s.bridge.GetUpdateChannel()
- if channel == updater.EarlyChannel {
- if _, err := s.bridge.SetUpdateChannel(updater.StableChannel); err != nil {
- s.Qml.NotifyManualUpdateError()
- return
- }
- }
-
- if err := s.bridge.ClearData(); err != nil {
- log.Error("While clearing cache: ", err)
- }
- // Clearing data removes everything (db, preferences, ...)
- // so everything has to be stopped and started again.
- s.restarter.SetToRestart()
- s.App.Quit()
-}
-
-func (s *FrontendQt) clearKeychain() {
- defer s.Qml.ProcessFinished()
- for _, user := range s.bridge.GetUsers() {
- if err := s.bridge.DeleteUser(user.ID(), false); err != nil {
- log.Error("While deleting user: ", err)
- if err == keychain.ErrNoKeychain { // Probably not needed anymore.
- s.Qml.NotifyHasNoKeychain()
- }
- }
- }
-}
-
-func (s *FrontendQt) logoutAccount(iAccount int) {
- defer s.Qml.ProcessFinished()
- userID := s.Accounts.get(iAccount).UserID()
- user, err := s.bridge.GetUser(userID)
- if err != nil {
- log.Error("While logging out ", userID, ": ", err)
- return
- }
- if err := user.Logout(); err != nil {
- log.Error("While logging out ", userID, ": ", err)
- }
-}
-
-func (s *FrontendQt) showLoginError(err error, scope string) bool {
- if err == nil {
- s.Qml.SetConnectionStatus(true) // If we are here connection is ok.
- return false
- }
- log.Warnf("%s: %v", scope, err)
- if err == pmapi.ErrNoConnection {
- s.Qml.SetConnectionStatus(false)
- s.SendNotification(TabAccount, s.Qml.CanNotReachAPI())
- s.Qml.ProcessFinished()
- return true
- }
- s.Qml.SetConnectionStatus(true) // If we are here connection is ok.
- if err == pmapi.ErrUpgradeApplication {
- return true
- }
- s.Qml.SetAddAccountWarning(err.Error(), -1)
- return true
-}
-
-// login returns:
-// -1: when error occurred
-// 0: when no 2FA and no MBOX
-// 1: when has 2FA
-// 2: when has no 2FA but have MBOX
-func (s *FrontendQt) login(login, password string) int {
- var err error
- s.authClient, s.auth, err = s.bridge.Login(login, []byte(password))
- if s.showLoginError(err, "login") {
- return -1
- }
- if s.auth.HasTwoFactor() {
- return 1
- }
- if s.auth.HasMailboxPassword() {
- return 2
- }
- return 0 // No 2FA, no mailbox password.
-}
-
-// auth2FA returns:
-// -1 : error (use SetAddAccountWarning to show message)
-// 0 : single password mode
-// 1 : two password mode
-func (s *FrontendQt) auth2FA(twoFacAuth string) int {
- var err error
- if s.auth == nil || s.authClient == nil {
- err = fmt.Errorf("missing authentication in auth2FA %p %p", s.auth, s.authClient)
- } else {
- err = s.authClient.Auth2FA(context.Background(), twoFacAuth)
- }
-
- if s.showLoginError(err, "auth2FA") {
- return -1
- }
-
- if s.auth.HasMailboxPassword() {
- return 1 // Ask for mailbox password.
- }
- return 0 // One password.
-}
-
-// addAccount adds an account. It should close login modal ProcessFinished if ok.
-func (s *FrontendQt) addAccount(mailboxPassword string) int {
- if s.auth == nil || s.authClient == nil {
- log.Errorf("Missing authentication in addAccount %p %p", s.auth, s.authClient)
- s.Qml.SetAddAccountWarning(s.Qml.WrongMailboxPassword(), -2)
- return -1
- }
-
- user, err := s.bridge.FinishLogin(s.authClient, s.auth, []byte(mailboxPassword))
- if err != nil {
- log.WithError(err).Error("Login was unsuccessful")
- s.Qml.SetAddAccountWarning("Failure: "+err.Error(), -2)
- return -1
- }
-
- s.userIDAdded = user.ID()
- s.eventListener.Emit(events.UserRefreshEvent, user.ID())
- s.Qml.ProcessFinished()
- return 0
-}
-
-func (s *FrontendQt) deleteAccount(iAccount int, removePreferences bool) {
- defer s.Qml.ProcessFinished()
- userID := s.Accounts.get(iAccount).UserID()
- if err := s.bridge.DeleteUser(userID, removePreferences); err != nil {
- log.Warn("deleteUser: cannot remove user: ", err)
- if err == keychain.ErrNoKeychain {
- s.Qml.NotifyHasNoKeychain()
- return
- }
- s.SendNotification(TabSettings, err.Error())
- return
- }
-}
diff --git a/internal/frontend/qt/frontend.go b/internal/frontend/qt/frontend.go
deleted file mode 100644
index c6b4f0f5..00000000
--- a/internal/frontend/qt/frontend.go
+++ /dev/null
@@ -1,728 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// +build build_qt
-
-// Package qt is the Qt User interface for Desktop bridge.
-//
-// The FrontendQt implements Frontend interface: `frontend.go`.
-// The helper functions are in `helpers.go`.
-// Notification specific is written in `notification.go`.
-// The AccountsModel is container providing account info to QML ListView.
-//
-// Since we are using QML there is only one Qt loop in `ui.go`.
-package qt
-
-import (
- "errors"
- "os"
- "runtime"
- "strconv"
- "strings"
- "sync"
- "time"
-
- "github.com/ProtonMail/go-autostart"
- "github.com/ProtonMail/proton-bridge/internal/bridge"
- "github.com/ProtonMail/proton-bridge/internal/config/settings"
- "github.com/ProtonMail/proton-bridge/internal/config/useragent"
- "github.com/ProtonMail/proton-bridge/internal/events"
- "github.com/ProtonMail/proton-bridge/internal/frontend/autoconfig"
- qtcommon "github.com/ProtonMail/proton-bridge/internal/frontend/qt-common"
- "github.com/ProtonMail/proton-bridge/internal/frontend/types"
- "github.com/ProtonMail/proton-bridge/internal/locations"
- "github.com/ProtonMail/proton-bridge/internal/updater"
- "github.com/ProtonMail/proton-bridge/pkg/keychain"
- "github.com/ProtonMail/proton-bridge/pkg/listener"
- "github.com/ProtonMail/proton-bridge/pkg/pmapi"
- "github.com/ProtonMail/proton-bridge/pkg/ports"
- "github.com/sirupsen/logrus"
- "github.com/skratchdot/open-golang/open"
- "github.com/therecipe/qt/core"
- "github.com/therecipe/qt/gui"
- "github.com/therecipe/qt/qml"
- "github.com/therecipe/qt/widgets"
-)
-
-var log = logrus.WithField("pkg", "frontend-qt")
-var accountMutex = &sync.Mutex{}
-
-// API between Bridge and Qt.
-//
-// With this interface it is possible to control Qt-Gui interface using pointers to
-// Qt and QML objects. QML signals and slots are connected via methods of GoQMLInterface.
-type FrontendQt struct {
- version string
- buildVersion string
- programName string
- showWindowOnStart bool
- panicHandler types.PanicHandler
- locations *locations.Locations
- settings *settings.Settings
- eventListener listener.Listener
- updater types.Updater
- userAgent *useragent.UserAgent
- bridge types.Bridger
- noEncConfirmator types.NoEncConfirmator
-
- App *widgets.QApplication // Main Application pointer.
- View *qml.QQmlApplicationEngine // QML engine pointer.
- MainWin *core.QObject // Pointer to main window inside QML.
- Qml *GoQMLInterface // Object accessible from both Go and QML for methods and signals.
- Accounts *AccountsModel // Providing data for accounts ListView.
- programVer string // Program version (shown in help).
-
- authClient pmapi.Client
-
- auth *pmapi.Auth
-
- autostart *autostart.App
-
- // expand userID when added
- userIDAdded string
-
- restarter types.Restarter
-
- // saving most up-to-date update info to install it manually
- updateInfo updater.VersionInfo
-
- initializing sync.WaitGroup
- initializationDone sync.Once
-}
-
-// New returns a new Qt frontend for the bridge.
-func New(
- version,
- buildVersion,
- programName string,
- showWindowOnStart bool,
- panicHandler types.PanicHandler,
- locations *locations.Locations,
- settings *settings.Settings,
- eventListener listener.Listener,
- updater types.Updater,
- userAgent *useragent.UserAgent,
- bridge types.Bridger,
- noEncConfirmator types.NoEncConfirmator,
- autostart *autostart.App,
- restarter types.Restarter,
-) *FrontendQt {
- userAgent.SetPlatform(core.QSysInfo_PrettyProductName())
-
- f := &FrontendQt{
- version: version,
- buildVersion: buildVersion,
- programName: programName,
- showWindowOnStart: showWindowOnStart,
- panicHandler: panicHandler,
- locations: locations,
- settings: settings,
- eventListener: eventListener,
- updater: updater,
- userAgent: userAgent,
- bridge: bridge,
- noEncConfirmator: noEncConfirmator,
- programVer: "v" + version,
- autostart: autostart,
- restarter: restarter,
- }
-
- // Initializing.Done is only called sync.Once. Please keep the increment
- // set to 1
- f.initializing.Add(1)
-
- return f
-}
-
-// InstanceExistAlert is a global warning window indicating an instance already exists.
-func (s *FrontendQt) InstanceExistAlert() {
- log.Warn("Instance already exists")
- qtcommon.QtSetupCoreAndControls(s.programName, s.programVer)
- s.App = widgets.NewQApplication(len(os.Args), os.Args)
- s.View = qml.NewQQmlApplicationEngine(s.App)
- s.View.AddImportPath("qrc:///")
- s.View.Load(core.NewQUrl3("qrc:/BridgeUI/InstanceExistsWindow.qml", 0))
- _ = gui.QGuiApplication_Exec()
-}
-
-// Loop function for Bridge interface.
-//
-// It runs QtExecute in main thread with no additional function.
-func (s *FrontendQt) Loop() (err error) {
- err = s.qtExecute(func(s *FrontendQt) error { return nil })
- return err
-}
-
-func (s *FrontendQt) NotifyManualUpdate(update updater.VersionInfo, canInstall bool) {
- s.SetVersion(update)
- s.Qml.SetUpdateCanInstall(canInstall)
- s.Qml.NotifyManualUpdate()
-}
-
-func (s *FrontendQt) SetVersion(version updater.VersionInfo) {
- s.Qml.SetUpdateVersion(version.Version.String())
- s.Qml.SetUpdateLandingPage(version.LandingPage)
- s.Qml.SetUpdateReleaseNotesLink(version.ReleaseNotesPage)
- s.updateInfo = version
-}
-
-func (s *FrontendQt) NotifySilentUpdateInstalled() {
- s.Qml.NotifySilentUpdateRestartNeeded()
-}
-
-func (s *FrontendQt) NotifySilentUpdateError(err error) {
- s.Qml.NotifySilentUpdateError()
-}
-
-func (s *FrontendQt) watchEvents() {
- s.WaitUntilFrontendIsReady()
-
- errorCh := s.eventListener.ProvideChannel(events.ErrorEvent)
- credentialsErrorCh := s.eventListener.ProvideChannel(events.CredentialsErrorEvent)
- outgoingNoEncCh := s.eventListener.ProvideChannel(events.OutgoingNoEncEvent)
- noActiveKeyForRecipientCh := s.eventListener.ProvideChannel(events.NoActiveKeyForRecipientEvent)
- internetOffCh := s.eventListener.ProvideChannel(events.InternetOffEvent)
- internetOnCh := s.eventListener.ProvideChannel(events.InternetOnEvent)
- secondInstanceCh := s.eventListener.ProvideChannel(events.SecondInstanceEvent)
- restartBridgeCh := s.eventListener.ProvideChannel(events.RestartBridgeEvent)
- addressChangedCh := s.eventListener.ProvideChannel(events.AddressChangedEvent)
- addressChangedLogoutCh := s.eventListener.ProvideChannel(events.AddressChangedLogoutEvent)
- logoutCh := s.eventListener.ProvideChannel(events.LogoutEvent)
- updateApplicationCh := s.eventListener.ProvideChannel(events.UpgradeApplicationEvent)
- newUserCh := s.eventListener.ProvideChannel(events.UserRefreshEvent)
- certIssue := s.eventListener.ProvideChannel(events.TLSCertIssue)
- for {
- select {
- case errorDetails := <-errorCh:
- imapIssue := strings.Contains(errorDetails, "IMAP failed")
- smtpIssue := strings.Contains(errorDetails, "SMTP failed")
- s.Qml.NotifyPortIssue(imapIssue, smtpIssue)
- case <-credentialsErrorCh:
- s.Qml.NotifyHasNoKeychain()
- case idAndSubject := <-outgoingNoEncCh:
- idAndSubjectSlice := strings.SplitN(idAndSubject, ":", 2)
- messageID := idAndSubjectSlice[0]
- subject := idAndSubjectSlice[1]
- s.Qml.ShowOutgoingNoEncPopup(messageID, subject)
- case email := <-noActiveKeyForRecipientCh:
- s.Qml.ShowNoActiveKeyForRecipient(email)
- case <-internetOffCh:
- s.Qml.SetConnectionStatus(false)
- case <-internetOnCh:
- s.Qml.SetConnectionStatus(true)
- case <-secondInstanceCh:
- s.Qml.ShowWindow()
- case <-restartBridgeCh:
- s.restarter.SetToRestart()
- // watchEvents is started in parallel with the Qt app.
- // If the event comes too early, app might not be ready yet.
- if s.App != nil {
- s.App.Quit()
- }
- case address := <-addressChangedCh:
- s.Qml.NotifyAddressChanged(address)
- case address := <-addressChangedLogoutCh:
- s.Qml.NotifyAddressChangedLogout(address)
- case userID := <-logoutCh:
- user, err := s.bridge.GetUser(userID)
- if err != nil {
- return
- }
- s.Qml.NotifyLogout(user.Username())
- case <-updateApplicationCh:
- s.Qml.ProcessFinished()
- s.Qml.NotifyForceUpdate()
- case <-newUserCh:
- s.Qml.LoadAccounts()
- case <-certIssue:
- s.Qml.ShowCertIssue()
- }
- }
-}
-
-// Loop function for tests.
-//
-// It runs QtExecute in new thread with function returning itself after setup.
-// Therefore it is possible to run tests on background.
-func (s *FrontendQt) Start() (err error) {
- uiready := make(chan *FrontendQt)
- go func() {
- err := s.qtExecute(func(self *FrontendQt) error {
- // NOTE: Trick to send back UI by channel to access functionality
- // inside application thread. Other only uninitialized `ui` is visible.
- uiready <- self
- return nil
- })
- if err != nil {
- log.Error(err)
- }
- uiready <- nil
- }()
-
- // Receive UI pointer and set all pointers.
- running := <-uiready
- s.App = running.App
- s.View = running.View
- s.MainWin = running.MainWin
- return nil
-}
-
-// InvMethod runs the function with name `method` defined in RootObject of the QML.
-// Used for tests.
-func (s *FrontendQt) InvMethod(method string) error {
- arg := core.NewQGenericArgument("", nil)
- PauseLong()
- isGoodMethod := core.QMetaObject_InvokeMethod4(s.MainWin, method, arg, arg, arg, arg, arg, arg, arg, arg, arg, arg)
- if isGoodMethod == false {
- return errors.New("Wrong method " + method)
- }
- return nil
-}
-
-// qtExecute is the main function for starting the Qt application.
-//
-// It is better to have just one Qt application per program (at least per same
-// thread). This functions reads the main user interface defined in QML files.
-// The files are appended to library by Qt-QRC.
-func (s *FrontendQt) qtExecute(Procedure func(*FrontendQt) error) error {
- qtcommon.QtSetupCoreAndControls(s.programName, s.programVer)
- s.App = widgets.NewQApplication(len(os.Args), os.Args)
- if runtime.GOOS == "linux" { // Fix default font.
- s.App.SetFont(gui.NewQFont2(FcMatchSans(), 12, int(gui.QFont__Normal), false), "")
- }
- s.App.SetQuitOnLastWindowClosed(false) // Just to make sure it's not closed.
-
- s.View = qml.NewQQmlApplicationEngine(s.App)
- // Add Go-QML bridge.
- s.Qml = NewGoQMLInterface(nil)
- s.Qml.SetIsShownOnStart(s.showWindowOnStart)
- s.Qml.SetFrontend(s) // provides access
- s.View.RootContext().SetContextProperty("go", s.Qml)
-
- // Set first start flag.
- s.Qml.SetIsFirstStart(s.settings.GetBool(settings.FirstStartGUIKey))
- s.settings.SetBool(settings.FirstStartGUIKey, false)
-
- // Check if it is first start after update (fresh version).
- lastVersion := s.settings.Get(settings.LastVersionKey)
- s.Qml.SetIsFreshVersion(lastVersion != "" && s.version != lastVersion)
- s.settings.Set(settings.LastVersionKey, s.version)
-
- // Add AccountsModel.
- s.Accounts = NewAccountsModel(nil)
- s.View.RootContext().SetContextProperty("accountsModel", s.Accounts)
- // Import path and load QML files.
- s.View.AddImportPath("qrc:///")
- s.View.Load(core.NewQUrl3("qrc:/ui.qml", 0))
-
- // List of used packages.
- s.Qml.SetCredits(bridge.Credits)
- s.Qml.SetFullversion(s.buildVersion)
-
- // Autostart: rewrite the current definition of autostart
- // - when it is the first time
- // - when starting after clear cache
- // - when there is already autostart file from past
- //
- // This will make sure that autostart will use the latest path to
- // launcher or bridge.
- isAutoStartEnabled := s.autostart.IsEnabled()
- if s.Qml.IsFirstStart() || isAutoStartEnabled {
- if isAutoStartEnabled {
- if err := s.autostart.Disable(); err != nil {
- log.
- WithField("first", s.Qml.IsFirstStart()).
- WithField("wasEnabled", isAutoStartEnabled).
- WithError(err).
- Error("Disable on start failed.")
- s.autostartError(err)
- }
- }
- if err := s.autostart.Enable(); err != nil {
- log.
- WithField("first", s.Qml.IsFirstStart()).
- WithField("wasEnabled", isAutoStartEnabled).
- WithError(err).
- Error("Enable on start failed.")
- s.autostartError(err)
- }
- }
- s.Qml.SetIsAutoStart(s.autostart.IsEnabled())
-
- s.Qml.SetIsAutoUpdate(s.settings.GetBool(settings.AutoUpdateKey))
- s.Qml.SetIsProxyAllowed(s.settings.GetBool(settings.AllowProxyKey))
- s.Qml.SetIsEarlyAccess(updater.UpdateChannel(s.settings.Get(settings.UpdateChannelKey)) == updater.EarlyChannel)
-
- availableKeychain := []string{}
- for chain := range keychain.Helpers {
- availableKeychain = append(availableKeychain, chain)
- }
- s.Qml.SetAvailableKeychain(availableKeychain)
- s.Qml.SetSelectedKeychain(s.settings.Get(settings.PreferredKeychainKey))
-
- // Set reporting of outgoing email without encryption.
- s.Qml.SetIsReportingOutgoingNoEnc(s.settings.GetBool(settings.ReportOutgoingNoEncKey))
-
- defaultIMAPPort, _ := strconv.Atoi(settings.DefaultIMAPPort)
- defaultSMTPPort, _ := strconv.Atoi(settings.DefaultSMTPPort)
-
- // IMAP/SMTP ports.
- s.Qml.SetIsDefaultPort(
- defaultIMAPPort == s.settings.GetInt(settings.IMAPPortKey) &&
- defaultSMTPPort == s.settings.GetInt(settings.SMTPPortKey),
- )
-
- // Check QML is loaded properly.
- if len(s.View.RootObjects()) == 0 {
- return errors.New("QML not loaded properly")
- }
-
- // Obtain main window (need for invoke method).
- s.MainWin = s.View.RootObjects()[0]
- SetupSystray(s)
-
- // Injected procedure for out-of-main-thread applications.
- if err := Procedure(s); err != nil {
- return err
- }
-
- go func() {
- defer s.panicHandler.HandlePanic()
- s.watchEvents()
- }()
-
- // Loop
- if ret := gui.QGuiApplication_Exec(); ret != 0 {
- err := errors.New("Event loop ended with return value:" + string(ret))
- log.Warn("QGuiApplication_Exec: ", err)
- return err
- }
- HideSystray()
- return nil
-}
-
-func (s *FrontendQt) openLogs() {
- logsPath, err := s.locations.ProvideLogsPath()
- if err != nil {
- return
- }
-
- go open.Run(logsPath)
-}
-
-func (s *FrontendQt) checkIsLatestVersionAndUpdate() bool {
- version, err := s.updater.Check()
-
- if err != nil {
- logrus.WithError(err).Error("An error occurred while checking updates manually")
- s.Qml.NotifyManualUpdateError()
- return false
- }
-
- s.SetVersion(version)
-
- if !s.updater.IsUpdateApplicable(version) {
- logrus.Debug("No need to update")
- return true
- }
-
- logrus.WithField("version", version.Version).Info("An update is available")
-
- if !s.updater.CanInstall(version) {
- logrus.Debug("A manual update is required")
- s.NotifyManualUpdate(version, false)
- return false
- }
-
- s.NotifyManualUpdate(version, true)
- return false
-}
-
-func (s *FrontendQt) checkAndOpenReleaseNotes() {
- go func() {
- _ = s.checkIsLatestVersionAndUpdate()
- s.Qml.OpenReleaseNotesExternally()
- }()
-}
-
-func (s *FrontendQt) checkForUpdates() {
- go func() {
- if s.checkIsLatestVersionAndUpdate() {
- s.Qml.NotifyVersionIsTheLatest()
- }
- }()
-}
-
-func (s *FrontendQt) openLicenseFile() {
- go open.Run(s.locations.GetLicenseFilePath())
-}
-
-func (s *FrontendQt) getLocalVersionInfo() {
- // NOTE: Fix this.
-}
-
-func (s *FrontendQt) sendBug(description, client, address string) (isOK bool) {
- isOK = true
- var accname = "No account logged in"
- if s.Accounts.Count() > 0 {
- accname = s.Accounts.get(0).Account()
- }
- if accname == "" {
- accname = "Unknown account"
- }
- if err := s.bridge.ReportBug(
- core.QSysInfo_ProductType(),
- core.QSysInfo_PrettyProductName(),
- description,
- accname,
- address,
- client,
- ); err != nil {
- log.Error("while sendBug: ", err)
- isOK = false
- }
- return
-}
-
-func (s *FrontendQt) getLastMailClient() string {
- return s.userAgent.String()
-}
-
-func (s *FrontendQt) configureAppleMail(iAccount, iAddress int) {
- acc := s.Accounts.get(iAccount)
-
- user, err := s.bridge.GetUser(acc.UserID())
- if err != nil {
- log.Warn("UserConfigFromKeychain failed: ", acc.Account(), err)
- s.SendNotification(TabAccount, s.Qml.GenericErrSeeLogs())
- return
- }
-
- imapPort := s.settings.GetInt(settings.IMAPPortKey)
- imapSSL := false
- smtpPort := s.settings.GetInt(settings.SMTPPortKey)
- smtpSSL := s.settings.GetBool(settings.SMTPSSLKey)
-
- // If configuring apple mail for Catalina or newer, users should use SSL.
- doRestart := false
- if !smtpSSL && useragent.IsCatalinaOrNewer() {
- smtpSSL = true
- s.settings.SetBool(settings.SMTPSSLKey, true)
- log.Warn("Detected Catalina or newer with bad SMTP SSL settings, now using SSL, bridge needs to restart")
- doRestart = true
- } else if smtpSSL {
- log.Debug("Bridge is already using SMTP SSL, no need to restart")
- } else {
- log.Debug("OS is pre-catalina (or not darwin at all), no need to change to SMTP SSL")
- }
-
- for _, autoConf := range autoconfig.Available() {
- if err := autoConf.Configure(imapPort, smtpPort, imapSSL, smtpSSL, user, iAddress); err != nil {
- log.Warn("Autoconfig failed: ", autoConf.Name(), err)
- s.SendNotification(TabAccount, s.Qml.GenericErrSeeLogs())
- return
- }
- }
-
- if doRestart {
- time.Sleep(2 * time.Second)
- s.restarter.SetToRestart()
- s.App.Quit()
- }
- return
-}
-
-func (s *FrontendQt) toggleAutoStart() {
- defer s.Qml.ProcessFinished()
- var err error
- wasEnabled := s.autostart.IsEnabled()
- if wasEnabled {
- err = s.autostart.Disable()
- } else {
- err = s.autostart.Enable()
- }
- isEnabled := s.autostart.IsEnabled()
- if err != nil {
- log.
- WithField("wasEnabled", wasEnabled).
- WithField("isEnabled", isEnabled).
- WithError(err).
- Error("Autostart change failed.")
- s.autostartError(err)
- }
- s.Qml.SetIsAutoStart(isEnabled)
-}
-
-func (s *FrontendQt) toggleAutoUpdate() {
- defer s.Qml.ProcessFinished()
-
- if s.settings.GetBool(settings.AutoUpdateKey) {
- s.settings.SetBool(settings.AutoUpdateKey, false)
- s.Qml.SetIsAutoUpdate(false)
- } else {
- s.settings.SetBool(settings.AutoUpdateKey, true)
- s.Qml.SetIsAutoUpdate(true)
- }
-}
-
-func (s *FrontendQt) toggleEarlyAccess() {
- defer s.Qml.ProcessFinished()
-
- channel := s.bridge.GetUpdateChannel()
- if channel == updater.EarlyChannel {
- channel = updater.StableChannel
- } else {
- channel = updater.EarlyChannel
- }
-
- needRestart, err := s.bridge.SetUpdateChannel(channel)
- s.Qml.SetIsEarlyAccess(channel == updater.EarlyChannel)
- if err != nil {
- s.Qml.NotifyManualUpdateError()
- return
- }
- if needRestart {
- s.restarter.SetToRestart()
- s.App.Quit()
- }
-}
-
-func (s *FrontendQt) toggleAllowProxy() {
- defer s.Qml.ProcessFinished()
-
- if s.settings.GetBool(settings.AllowProxyKey) {
- s.settings.SetBool(settings.AllowProxyKey, false)
- s.bridge.DisallowProxy()
- s.Qml.SetIsProxyAllowed(false)
- } else {
- s.settings.SetBool(settings.AllowProxyKey, true)
- s.bridge.AllowProxy()
- s.Qml.SetIsProxyAllowed(true)
- }
-}
-
-func (s *FrontendQt) getIMAPPort() string {
- return s.settings.Get(settings.IMAPPortKey)
-}
-
-func (s *FrontendQt) getSMTPPort() string {
- return s.settings.Get(settings.SMTPPortKey)
-}
-
-// Return 0 -- port is free to use for server.
-// Return 1 -- port is occupied.
-func (s *FrontendQt) isPortOpen(portStr string) int {
- portInt, err := strconv.Atoi(portStr)
- if err != nil {
- return 1
- }
- if !ports.IsPortFree(portInt) {
- return 1
- }
- return 0
-}
-
-func (s *FrontendQt) setPortsAndSecurity(imapPort, smtpPort string, useSTARTTLSforSMTP bool) {
- s.settings.Set(settings.IMAPPortKey, imapPort)
- s.settings.Set(settings.SMTPPortKey, smtpPort)
- s.settings.SetBool(settings.SMTPSSLKey, !useSTARTTLSforSMTP)
-}
-
-func (s *FrontendQt) isSMTPSTARTTLS() bool {
- return !s.settings.GetBool(settings.SMTPSSLKey)
-}
-
-func (s *FrontendQt) switchAddressModeUser(iAccount int) {
- defer s.Qml.ProcessFinished()
- userID := s.Accounts.get(iAccount).UserID()
- user, err := s.bridge.GetUser(userID)
- if err != nil {
- log.Error("Get user for switch address mode failed: ", err)
- s.SendNotification(TabAccount, s.Qml.GenericErrSeeLogs())
- return
- }
- if err := user.SwitchAddressMode(); err != nil {
- log.Error("Switch address mode failed: ", err)
- s.SendNotification(TabAccount, s.Qml.GenericErrSeeLogs())
- return
- }
- s.userIDAdded = userID
-}
-
-func (s *FrontendQt) autostartError(err error) {
- if strings.Contains(err.Error(), "permission denied") {
- s.Qml.FailedAutostartCode("permission")
- } else if strings.Contains(err.Error(), "error code: 0x") {
- errorCode := err.Error()
- errorCode = errorCode[len(errorCode)-8:]
- s.Qml.FailedAutostartCode(errorCode)
- } else {
- s.Qml.FailedAutostartCode("")
- }
-}
-
-func (s *FrontendQt) toggleIsReportingOutgoingNoEnc() {
- shouldReport := !s.Qml.IsReportingOutgoingNoEnc()
- s.settings.SetBool(settings.ReportOutgoingNoEncKey, shouldReport)
- s.Qml.SetIsReportingOutgoingNoEnc(shouldReport)
-}
-
-func (s *FrontendQt) shouldSendAnswer(messageID string, shouldSend bool) {
- s.noEncConfirmator.ConfirmNoEncryption(messageID, shouldSend)
-}
-
-func (s *FrontendQt) saveOutgoingNoEncPopupCoord(x, y float32) {
- //prefs.SetFloat(prefs.OutgoingNoEncPopupCoordX, x)
- //prefs.SetFloat(prefs.OutgoingNoEncPopupCoordY, y)
-}
-
-func (s *FrontendQt) startManualUpdate() {
- go func() {
- err := s.updater.InstallUpdate(s.updateInfo)
-
- if err != nil {
- logrus.WithError(err).Error("An error occurred while installing updates manually")
- s.Qml.NotifyManualUpdateError()
- } else {
- s.Qml.NotifyManualUpdateRestartNeeded()
- }
- }()
-}
-
-func (s *FrontendQt) WaitUntilFrontendIsReady() {
- s.initializing.Wait()
-}
-
-// setGUIIsReady unlocks the WaitFrontendIsReady.
-func (s *FrontendQt) setGUIIsReady() {
- s.initializationDone.Do(func() {
- s.initializing.Done()
- })
-}
-
-func (s *FrontendQt) getKeychain() string {
- return s.bridge.GetKeychainApp()
-}
-
-func (s *FrontendQt) setKeychain(keychain string) {
- if keychain != s.bridge.GetKeychainApp() {
- s.bridge.SetKeychainApp(keychain)
-
- s.restarter.SetToRestart()
- s.App.Quit()
- }
-}
diff --git a/internal/frontend/qt/frontend_nogui.go b/internal/frontend/qt/frontend_nogui.go
deleted file mode 100644
index 872c7ffd..00000000
--- a/internal/frontend/qt/frontend_nogui.go
+++ /dev/null
@@ -1,82 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// +build !build_qt
-
-package qt
-
-import (
- "fmt"
- "net/http"
-
- "github.com/ProtonMail/go-autostart"
- "github.com/ProtonMail/proton-bridge/internal/config/settings"
- "github.com/ProtonMail/proton-bridge/internal/config/useragent"
- "github.com/ProtonMail/proton-bridge/internal/frontend/types"
- "github.com/ProtonMail/proton-bridge/internal/locations"
- "github.com/ProtonMail/proton-bridge/internal/updater"
- "github.com/ProtonMail/proton-bridge/pkg/listener"
- "github.com/sirupsen/logrus"
-)
-
-var log = logrus.WithField("pkg", "frontend-nogui") //nolint[gochecknoglobals]
-
-type FrontendHeadless struct{}
-
-func (s *FrontendHeadless) Loop() error {
- log.Info("Check status on localhost:8081")
- http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
- fmt.Fprintf(w, "Bridge is running")
- })
- return http.ListenAndServe(":8081", nil)
-}
-
-func (s *FrontendHeadless) NotifyManualUpdate(update updater.VersionInfo, canInstall bool) {
- // NOTE: Save the update somewhere so that it can be installed when user chooses "install now".
-}
-
-func (s *FrontendHeadless) WaitUntilFrontendIsReady() {
-}
-
-func (s *FrontendHeadless) SetVersion(update updater.VersionInfo) {
-}
-
-func (s *FrontendHeadless) NotifySilentUpdateInstalled() {
-}
-
-func (s *FrontendHeadless) NotifySilentUpdateError(err error) {
-}
-
-func (s *FrontendHeadless) InstanceExistAlert() {}
-
-func New(
- version,
- buildVersion, appName string,
- showWindowOnStart bool,
- panicHandler types.PanicHandler,
- locations *locations.Locations,
- settings *settings.Settings,
- eventListener listener.Listener,
- updater types.Updater,
- userAgent *useragent.UserAgent,
- bridge types.Bridger,
- noEncConfirmator types.NoEncConfirmator,
- autostart *autostart.App,
- restarter types.Restarter,
-) *FrontendHeadless {
- return &FrontendHeadless{}
-}
diff --git a/internal/frontend/qt/helpers.go b/internal/frontend/qt/helpers.go
deleted file mode 100644
index 1c02e73e..00000000
--- a/internal/frontend/qt/helpers.go
+++ /dev/null
@@ -1,79 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// +build build_qt
-
-package qt
-
-import (
- "bufio"
- "os"
- "os/exec"
- "time"
-
- "github.com/therecipe/qt/core"
-)
-
-// NewQByteArrayFromString is a wrapper for new QByteArray from string.
-func NewQByteArrayFromString(name string) *core.QByteArray {
- return core.NewQByteArray2(name, len(name))
-}
-
-// NewQVariantString is a wrapper for QVariant alocator String.
-func NewQVariantString(data string) *core.QVariant {
- return core.NewQVariant1(data)
-}
-
-// NewQVariantStringArray is a wrapper for QVariant alocator String Array.
-func NewQVariantStringArray(data []string) *core.QVariant {
- return core.NewQVariant1(data)
-}
-
-// NewQVariantBool is a wrapper for QVariant alocator Bool.
-func NewQVariantBool(data bool) *core.QVariant {
- return core.NewQVariant1(data)
-}
-
-// NewQVariantInt is a wrapper for QVariant alocator Int.
-func NewQVariantInt(data int) *core.QVariant {
- return core.NewQVariant1(data)
-}
-
-// Pause is used to show GUI tests.
-func Pause() {
- time.Sleep(500 * time.Millisecond)
-}
-
-// PauseLong is used to diplay GUI tests.
-func PauseLong() {
- time.Sleep(3 * time.Second)
-}
-
-// FIXME: Not working in test...
-func WaitForEnter() {
- log.Print("Press 'Enter' to continue...")
- bufio.NewReader(os.Stdin).ReadBytes('\n')
-}
-
-func FcMatchSans() (family string) {
- family = "DejaVu Sans"
- fcMatch, err := exec.Command("fc-match", "-f", "'%{family}'", "sans-serif").Output()
- if err == nil {
- return string(fcMatch)
- }
- return
-}
diff --git a/internal/frontend/qt/notification.go b/internal/frontend/qt/notification.go
deleted file mode 100644
index 84f3f664..00000000
--- a/internal/frontend/qt/notification.go
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// +build build_qt
-
-package qt
-
-const (
- TabAccount = 0
- TabSettings = 1
- TabHelp = 2
- TabQuit = 4
- TabUpdates = 100
- TabAddAccount = -1
-)
-
-func (s *FrontendQt) SendNotification(tabIndex int, msg string) {
- s.Qml.NotifyBubble(tabIndex, msg)
-}
diff --git a/internal/frontend/qt/systray.go b/internal/frontend/qt/systray.go
deleted file mode 100644
index efe6fa38..00000000
--- a/internal/frontend/qt/systray.go
+++ /dev/null
@@ -1,117 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// +build build_qt
-
-package qt
-
-import (
- "runtime"
-
- "github.com/therecipe/qt/core"
- "github.com/therecipe/qt/gui"
- "github.com/therecipe/qt/widgets"
-)
-
-const (
- systrayNormal = ""
- systrayWarning = "-warn"
- systrayError = "-error"
-)
-
-func min(a, b int) int {
- if b < a {
- return b
- }
- return a
-}
-
-func max(a, b int) int {
- if b > a {
- return b
- }
- return a
-}
-
-var systray *widgets.QSystemTrayIcon
-
-func SetupSystray(frontend *FrontendQt) {
- systray = widgets.NewQSystemTrayIcon(nil)
- NormalSystray()
- systray.SetToolTip(frontend.programName)
- systray.SetContextMenu(createMenu(frontend, systray))
-
- if runtime.GOOS != "darwin" {
- systray.ConnectActivated(func(reason widgets.QSystemTrayIcon__ActivationReason) {
- switch reason {
- case widgets.QSystemTrayIcon__Trigger, widgets.QSystemTrayIcon__DoubleClick:
- frontend.Qml.ShowWindow()
- default:
- systray.ContextMenu().Exec2(menuPosition(systray), nil)
- }
- })
- }
-
- systray.Show()
-}
-
-func qsTr(msg string) string {
- return systray.Tr(msg, "Systray menu", -1)
-}
-
-func createMenu(frontend *FrontendQt, systray *widgets.QSystemTrayIcon) *widgets.QMenu {
- menu := widgets.NewQMenu(nil)
- menu.AddAction(qsTr("Open")).ConnectTriggered(func(ok bool) { frontend.Qml.ShowWindow() })
- menu.AddAction(qsTr("Help")).ConnectTriggered(func(ok bool) { frontend.Qml.ShowHelp() })
- menu.AddAction(qsTr("Quit")).ConnectTriggered(func(ok bool) { frontend.Qml.ShowQuit() })
- return menu
-}
-
-func menuPosition(systray *widgets.QSystemTrayIcon) *core.QPoint {
- var availRec = gui.QGuiApplication_PrimaryScreen().AvailableGeometry()
- var trayRec = systray.Geometry()
- var x = max(availRec.Left(), min(trayRec.X(), availRec.Right()-trayRec.Width()))
- var y = max(availRec.Top(), min(trayRec.Y(), availRec.Bottom()-trayRec.Height()))
- return core.NewQPoint2(x, y)
-}
-
-func showSystray(systrayType string) {
- path := ":/ProtonUI/images/systray" + systrayType
- if runtime.GOOS == "darwin" {
- path += "-mono"
- }
- path += ".png"
- icon := gui.NewQIcon5(path)
- icon.SetIsMask(true)
- systray.SetIcon(icon)
-}
-
-func NormalSystray() {
- showSystray(systrayNormal)
-}
-
-func HighlightSystray() {
- showSystray(systrayWarning)
-}
-
-func ErrorSystray() {
- showSystray(systrayError)
-}
-
-func HideSystray() {
- systray.Hide()
-}
diff --git a/internal/frontend/qt/translate.ts b/internal/frontend/qt/translate.ts
deleted file mode 100644
index 468ad908..00000000
--- a/internal/frontend/qt/translate.ts
+++ /dev/null
@@ -1,656 +0,0 @@
-
-
-
-
- AccountDelegate
-
-
- Logout
-
-
-
-
- Remove
-
-
-
-
- connected
-
-
-
-
- Log out
-
-
-
-
-
- disconnected
-
-
-
-
-
- Log in
-
-
-
-
- AccountView
-
-
- No accounts added
-
-
-
-
- ACCOUNT
-
-
-
-
- STATUS
-
-
-
-
- ACTIONS
-
-
-
-
- AddAccountBar
-
-
- Add Account
-
-
-
-
- Help
-
-
-
-
- BubbleMenu
-
-
- About
-
-
-
-
- BugReportWindow
-
-
- Please write a brief description of the bug(s) you have encountered...
-
-
-
-
- Email client:
-
-
-
-
- Contact email:
-
-
-
-
- Bug reports are not end-to-end encrypted!
-
-
-
-
- Please do not send any sensitive information.
-
-
-
-
- Contact us at security@protonmail.com for critical security issues.
-
-
-
-
- Cancel
-
-
-
-
- Send
-
-
-
-
- Field required
-
-
-
-
- DialogAddUser
-
-
- Log in to your ProtonMail account
-
-
-
-
- Username:
-
-
-
-
- Cancel
-
-
-
-
-
-
- Next
-
-
-
-
- Sign Up for an Account
-
-
-
-
- Password for %1
-
-
-
-
- Mailbox password for %1
-
-
-
-
- Two Factor Code
-
-
-
-
-
- Back
-
-
-
-
- Logging in
-
-
-
-
- Adding account, please wait ...
-
-
-
-
- Required field
-
-
-
-
- DialogPortChange
-
-
- IMAP port
-
-
-
-
- SMTP port
-
-
-
-
- Cancel
-
-
-
-
- Okay
-
-
-
-
- Settings will be applied after next start. You may need to re-configure your email client.
-
-
-
-
- Bridge will now restart.
-
-
-
-
- DialogYesNo
-
-
- Additionally delete all stored preferences and data
-
-
-
-
- No
-
-
-
-
- Yes
-
-
-
-
- Waiting...
-
-
-
-
- Close Bridge
-
-
-
-
- Are you sure you want to close the Bridge?
-
-
-
-
- Closing Bridge...
-
-
-
-
- Logout
-
-
-
-
- Logging out...
-
-
-
-
- Delete account
-
-
-
-
- Are you sure you want to remove this account?
-
-
-
-
- Deleting ...
-
-
-
-
- Clear keychain
-
-
-
-
- Are you sure you want to clear your keychain?
-
-
-
-
- Clearing the keychain ...
-
-
-
-
- Clear cache
-
-
-
-
- Are you sure you want to clear your local cache?
-
-
-
-
- Clearing the cache ...
-
-
-
-
- Checking for updates ...
-
-
-
-
- Turning on automatic start of Bridge...
-
-
-
-
- Turning off automatic start of Bridge...
-
-
-
-
- You have the latest version!
-
-
-
-
- Gui
-
-
- Account %1 has been disconnected. Please log in to continue to use the Bridge with this account.
-
-
-
-
- Incorrect username or password.
- notification
-
-
-
-
-
-
- Incorrect mailbox password.
- notification
-
-
-
-
-
-
- Cannot contact server, please check your internet connection.
- notification
-
-
-
-
-
-
- Credentials could not be removed.
- notification
-
-
-
-
-
-
- Unable to submit bug report.
- notification
-
-
-
-
-
-
- Bug report successfully sent.
- notification
-
-
-
-
-
-
- HelpView
-
-
- Logs
-
-
-
-
- Report Bug
-
-
-
-
- Setup Guide
-
-
-
-
- Check for Updates
-
-
-
-
- Credits
-
-
-
-
- HelperPane
-
-
- Skip
-
-
-
-
- Back
-
-
-
-
- Next
-
-
-
-
- You can add, delete, logout account. Expand account to see settings.
-
-
-
-
- This is settings windows: Clear cache, list logs, ...
-
-
-
-
- Welcome to ProtonMail Bridge! Add account to start.
-
-
-
-
- InfoWindow
-
-
- IMAP SETTINGS
-
-
-
-
-
- Hostname:
-
-
-
-
-
- Port:
-
-
-
-
-
- Username:
-
-
-
-
-
- Password:
-
-
-
-
- SMTP SETTINGS
-
-
-
-
- Configure Apple Mail
-
-
-
-
- InformationBar
-
-
- An update is available.
-
-
-
-
- No Internet connection
-
-
-
-
- Install
-
-
-
-
- Retry
-
-
-
-
- Dismiss
-
-
-
-
- InstanceExistsWindow
-
-
- ProtonMail Bridge
-
-
-
-
- Warning: Instance exists
-
-
-
-
- An instance of the ProtonMail Bridge is already running.
-
-
-
-
- Please close the existing ProtonMail Bridge process before starting a new one.
-
-
-
-
- This program will close now.
-
-
-
-
- Okay
-
-
-
-
- MainWindow
-
-
- ProtonMail Bridge
-
-
-
-
- Accounts
-
-
-
-
- Settings
-
-
-
-
- Help
-
-
-
-
- Click here to start
-
-
-
-
- Credits
-
-
-
-
- Information about version
-
-
-
-
- SettingsView
-
-
- Clear Cache
-
-
-
-
-
- Clear
-
-
-
-
- Clear Keychain
-
-
-
-
- Automatically Start Bridge
-
-
-
-
- Advanced settings
-
-
-
-
- Change SMTP/IMAP Ports
-
-
-
-
- Change
-
-
-
-
- StatusFooter
-
-
- Quit
-
-
-
-
- TabLabels
-
-
- Close Bridge
-
-
-
-
diff --git a/internal/frontend/qt/ui.go b/internal/frontend/qt/ui.go
deleted file mode 100644
index 21be8472..00000000
--- a/internal/frontend/qt/ui.go
+++ /dev/null
@@ -1,215 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge 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.
-//
-// ProtonMail Bridge 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 ProtonMail Bridge. If not, see .
-
-// +build build_qt
-
-package qt
-
-import (
- "runtime"
-
- "github.com/therecipe/qt/core"
-)
-
-// GoQMLInterface between go and qml.
-//
-// Here we implement all the signals / methods.
-type GoQMLInterface struct {
- core.QObject
-
- _ func() `constructor:"init"`
-
- _ bool `property:"isAutoStart"`
- _ bool `property:"isAutoUpdate"`
- _ bool `property:"isEarlyAccess"`
- _ bool `property:"isProxyAllowed"`
- _ string `property:"currentAddress"`
- _ string `property:"goos"`
- _ string `property:"credits"`
- _ bool `property:"isShownOnStart"`
- _ bool `property:"isFirstStart"`
- _ bool `property:"isFreshVersion"`
- _ bool `property:"isConnectionOK"`
- _ bool `property:"isDefaultPort"`
-
- _ string `property:"programTitle"`
- _ string `property:"fullversion"`
- _ string `property:"downloadLink"`
-
- _ string `property:"updateState"`
- _ string `property:"updateVersion"`
- _ bool `property:"updateCanInstall"`
- _ string `property:"updateLandingPage"`
- _ string `property:"updateReleaseNotesLink"`
- _ func() `signal:"notifyManualUpdate"`
- _ func() `signal:"notifyManualUpdateRestartNeeded"`
- _ func() `signal:"notifyManualUpdateError"`
- _ func() `signal:"notifyForceUpdate"`
- _ func() `signal:"notifySilentUpdateRestartNeeded"`
- _ func() `signal:"notifySilentUpdateError"`
- _ func() `slot:"checkForUpdates"`
- _ func() `slot:"checkAndOpenReleaseNotes"`
- _ func() `signal:"openReleaseNotesExternally"`
- _ func() `slot:"startManualUpdate"`
- _ func() `slot:"guiIsReady"`
-
- _ []string `property:"availableKeychain"`
- _ string `property:"selectedKeychain"`
-
- // Translations.
- _ string `property:"wrongCredentials"`
- _ string `property:"wrongMailboxPassword"`
- _ string `property:"canNotReachAPI"`
- _ string `property:"credentialsNotRemoved"`
- _ string `property:"versionCheckFailed"`
- _ string `property:"failedAutostartPerm"`
- _ string `property:"failedAutostart"`
- _ string `property:"genericErrSeeLogs"`
-
- _ float32 `property:"progress"`
- _ string `property:"progressDescription"`
-
- _ func(isAvailable bool) `signal:"setConnectionStatus"`
-
- _ func() `slot:"setToRestart"`
-
- _ func(systX, systY, systW, systH int) `signal:"toggleMainWin"`
-
- _ func() `signal:"processFinished"`
- _ func() `signal:"openManual"`
- _ func(showMessage bool) `signal:"runCheckVersion"`
- _ func() `signal:"toggleMainWin"`
-
- _ func() `signal:"showWindow"`
- _ func() `signal:"showHelp"`
- _ func() `signal:"showQuit"`
-
- _ func() `slot:"toggleAutoStart"`
- _ func() `slot:"toggleAutoUpdate"`
- _ func() `slot:"toggleEarlyAccess"`
- _ func() `slot:"toggleAllowProxy"`
- _ func() `slot:"loadAccounts"`
- _ func() `slot:"openLogs"`
- _ func() `slot:"clearCache"`
- _ func() `slot:"clearKeychain"`
- _ func() `slot:"highlightSystray"`
- _ func() `slot:"errorSystray"`
- _ func() `slot:"normalSystray"`
-
- _ func() `slot:"openLicenseFile"`
- _ func() `slot:"getLocalVersionInfo"`
- _ func(showMessage bool) `slot:"isNewVersionAvailable"`
- _ func() string `slot:"getBackendVersion"`
- _ func() string `slot:"getIMAPPort"`
- _ func() string `slot:"getSMTPPort"`
- _ func() string `slot:"getLastMailClient"`
- _ func(portStr string) int `slot:"isPortOpen"`
- _ func(imapPort, smtpPort string, useSTARTTLSforSMTP bool) `slot:"setPortsAndSecurity"`
- _ func() bool `slot:"isSMTPSTARTTLS"`
-
- _ func(description, client, address string) bool `slot:"sendBug"`
-
- _ func(tabIndex int, message string) `signal:"notifyBubble"`
- _ func(tabIndex int, message string) `signal:"silentBubble"`
- _ func() `signal:"bubbleClosed"`
-
- _ func(iAccount int, removePreferences bool) `slot:"deleteAccount"`
- _ func(iAccount int) `slot:"logoutAccount"`
- _ func(iAccount int, iAddress int) `slot:"configureAppleMail"`
- _ func(iAccount int) `signal:"switchAddressMode"`
-
- _ func(login, password string) int `slot:"login"`
- _ func(twoFacAuth string) int `slot:"auth2FA"`
- _ func(mailboxPassword string) int `slot:"addAccount"`
- _ func(message string, changeIndex int) `signal:"setAddAccountWarning"`
-
- _ func() `signal:"notifyVersionIsTheLatest"`
- _ func() `signal:"notifyKeychainRebuild"`
- _ func() `signal:"notifyHasNoKeychain"`
- _ func(accname string) `signal:"notifyLogout"`
- _ func(accname string) `signal:"notifyAddressChanged"`
- _ func(accname string) `signal:"notifyAddressChangedLogout"`
- _ func(busyPortIMAP, busyPortSMTP bool) `signal:"notifyPortIssue"`
- _ func(code string) `signal:"failedAutostartCode"`
-
- _ bool `property:"isReportingOutgoingNoEnc"`
- _ func() `slot:"toggleIsReportingOutgoingNoEnc"`
- _ func(messageID string, shouldSend bool) `slot:"shouldSendAnswer"`
- _ func(messageID, subject string) `signal:"showOutgoingNoEncPopup"`
- _ func(x, y float32) `signal:"setOutgoingNoEncPopupCoord"`
- _ func(x, y float32) `slot:"saveOutgoingNoEncPopupCoord"`
- _ func(recipient string) `signal:"showNoActiveKeyForRecipient"`
- _ func() `signal:"showCertIssue"`
-
- _ func(hasError bool) `signal:"updateFinished"`
-}
-
-// init is basically the constructor.
-func (s *GoQMLInterface) init() {}
-
-// SetFrontend connects all slots and signals from Go to QML.
-func (s *GoQMLInterface) SetFrontend(f *FrontendQt) {
- s.ConnectToggleAutoStart(f.toggleAutoStart)
- s.ConnectToggleEarlyAccess(f.toggleEarlyAccess)
- s.ConnectToggleAutoUpdate(f.toggleAutoUpdate)
- s.ConnectToggleAllowProxy(f.toggleAllowProxy)
- s.ConnectLoadAccounts(f.loadAccounts)
- s.ConnectOpenLogs(f.openLogs)
- s.ConnectClearCache(f.clearCache)
- s.ConnectClearKeychain(f.clearKeychain)
- s.ConnectOpenLicenseFile(f.openLicenseFile)
- s.ConnectStartManualUpdate(f.startManualUpdate)
- s.ConnectGuiIsReady(f.setGUIIsReady)
- s.ConnectGetLocalVersionInfo(f.getLocalVersionInfo)
- s.ConnectCheckForUpdates(f.checkForUpdates)
- s.ConnectGetIMAPPort(f.getIMAPPort)
- s.ConnectGetSMTPPort(f.getSMTPPort)
- s.ConnectGetLastMailClient(f.getLastMailClient)
- s.ConnectIsPortOpen(f.isPortOpen)
- s.ConnectIsSMTPSTARTTLS(f.isSMTPSTARTTLS)
-
- s.ConnectSendBug(f.sendBug)
-
- s.ConnectDeleteAccount(f.deleteAccount)
- s.ConnectLogoutAccount(f.logoutAccount)
- s.ConnectConfigureAppleMail(f.configureAppleMail)
- s.ConnectLogin(f.login)
- s.ConnectAuth2FA(f.auth2FA)
- s.ConnectAddAccount(f.addAccount)
- s.ConnectSetPortsAndSecurity(f.setPortsAndSecurity)
-
- s.ConnectHighlightSystray(HighlightSystray)
- s.ConnectErrorSystray(ErrorSystray)
- s.ConnectNormalSystray(NormalSystray)
- s.ConnectSwitchAddressMode(f.switchAddressModeUser)
-
- s.SetGoos(runtime.GOOS)
- s.SetProgramTitle(f.programName)
-
- s.ConnectGetBackendVersion(func() string {
- return f.programVer
- })
-
- s.ConnectSetToRestart(f.restarter.SetToRestart)
-
- s.ConnectToggleIsReportingOutgoingNoEnc(f.toggleIsReportingOutgoingNoEnc)
- s.ConnectShouldSendAnswer(f.shouldSendAnswer)
- s.ConnectSaveOutgoingNoEncPopupCoord(f.saveOutgoingNoEncPopupCoord)
-
- s.ConnectSetSelectedKeychain(f.setKeychain)
- s.ConnectSelectedKeychain(f.getKeychain)
-}
diff --git a/internal/frontend/resources.qrc b/internal/frontend/resources.qrc
deleted file mode 100644
index 3e1ca4f4..00000000
--- a/internal/frontend/resources.qrc
+++ /dev/null
@@ -1,115 +0,0 @@
-
-
-
-
- ./qml/ProtonUI/qmldir
- ./qml/ProtonUI/AccessibleButton.qml
- ./qml/ProtonUI/AccessibleText.qml
- ./qml/ProtonUI/AccessibleSelectableText.qml
- ./qml/ProtonUI/AccountView.qml
- ./qml/ProtonUI/AddAccountBar.qml
- ./qml/ProtonUI/BubbleNote.qml
- ./qml/ProtonUI/BugReportWindow.qml
- ./qml/ProtonUI/ButtonIconText.qml
- ./qml/ProtonUI/ButtonRounded.qml
- ./qml/ProtonUI/CheckBoxLabel.qml
- ./qml/ProtonUI/ClickIconText.qml
- ./qml/ProtonUI/Dialog.qml
- ./qml/ProtonUI/DialogAddUser.qml
- ./qml/ProtonUI/DialogUpdate.qml
- ./qml/ProtonUI/DialogConnectionTroubleshoot.qml
- ./qml/ProtonUI/FileAndFolderSelect.qml
- ./qml/ProtonUI/InfoToolTip.qml
- ./qml/ProtonUI/InformationBar.qml
- ./qml/ProtonUI/InputBox.qml
- ./qml/ProtonUI/InputField.qml
- ./qml/ProtonUI/InstanceExistsWindow.qml
- ./qml/ProtonUI/LogoHeader.qml
- ./qml/ProtonUI/PopupMessage.qml
- ./qml/ProtonUI/RoundedRectangle.qml
- ./qml/ProtonUI/Style.qml
- ./qml/ProtonUI/TabButton.qml
- ./qml/ProtonUI/TabLabels.qml
- ./qml/ProtonUI/TextLabel.qml
- ./qml/ProtonUI/TextValue.qml
- ./qml/ProtonUI/TLSCertPinIssueBar.qml
- ./qml/ProtonUI/WindowTitleBar.qml
- ./share/fontawesome-webfont.ttf
-
-
- ./share/icons/rounded-systray.png
- ./share/icons/rounded-syswarn.png
- ./share/icons/rounded-syswarn.png
- ./share/icons/white-systray.png
- ./share/icons/white-syswarn.png
- ./share/icons/white-syserror.png
- ./share/icons/rounded-app.png
- ./share/icons/pm_logo.png
- ./share/icons/win10_Dash.png
- ./share/icons/win10_Times.png
- ./share/icons/macos_gray.png
- ./share/icons/macos_red.png
- ./share/icons/macos_red_hl.png
- ./share/icons/macos_red_dark.png
- ./share/icons/macos_yellow.png
- ./share/icons/macos_yellow_hl.png
- ./share/icons/macos_yellow_dark.png
-
-
- ./qml/BridgeUI/qmldir
- ./qml/BridgeUI/AccountDelegate.qml
- ./qml/BridgeUI/BubbleMenu.qml
- ./qml/BridgeUI/Credits.qml
- ./qml/BridgeUI/DialogFirstStart.qml
- ./qml/BridgeUI/DialogKeychainChange.qml
- ./qml/BridgeUI/DialogPortChange.qml
- ./qml/BridgeUI/DialogYesNo.qml
- ./qml/BridgeUI/DialogTLSCertInfo.qml
- ./qml/BridgeUI/HelpView.qml
- ./qml/BridgeUI/InfoWindow.qml
- ./qml/BridgeUI/MainWindow.qml
- ./qml/BridgeUI/ManualWindow.qml
- ./qml/BridgeUI/OutgoingNoEncPopup.qml
- ./qml/BridgeUI/SettingsView.qml
- ./qml/BridgeUI/StatusFooter.qml
-
-
- ./qml/ImportExportUI/qmldir
- ./qml/ImportExportUI/AccountDelegate.qml
- ./qml/ImportExportUI/Credits.qml
- ./qml/ImportExportUI/DateBox.qml
- ./qml/ImportExportUI/DateInput.qml
- ./qml/ImportExportUI/DateRange.qml
- ./qml/ImportExportUI/DateRangeMenu.qml
- ./qml/ImportExportUI/DateRangeFunctions.qml
- ./qml/ImportExportUI/DialogExport.qml
- ./qml/ImportExportUI/DialogImport.qml
- ./qml/ImportExportUI/DialogYesNo.qml
- ./qml/ImportExportUI/ExportStructure.qml
- ./qml/ImportExportUI/FilterStructure.qml
- ./qml/ImportExportUI/FolderRowButton.qml
- ./qml/ImportExportUI/HelpView.qml
- ./qml/ImportExportUI/IEStyle.qml
- ./qml/ImportExportUI/ImportDelegate.qml
- ./qml/ImportExportUI/ImportReport.qml
- ./qml/ImportExportUI/ImportReportCell.qml
- ./qml/ImportExportUI/ImportSourceButton.qml
- ./qml/ImportExportUI/ImportStructure.qml
- ./qml/ImportExportUI/InlineDateRange.qml
- ./qml/ImportExportUI/InlineLabelSelect.qml
- ./qml/ImportExportUI/LabelIconList.qml
- ./qml/ImportExportUI/MainWindow.qml
- ./qml/ImportExportUI/OutputFormat.qml
- ./qml/ImportExportUI/PopupEditFolder.qml
- ./qml/ImportExportUI/SelectFolderMenu.qml
- ./qml/ImportExportUI/SelectLabelsMenu.qml
- ./qml/ImportExportUI/SettingsView.qml
- ./share/icons/folder_open.png
- ./share/icons/envelope_open.png
-
-
- ./qml/Gui.qml
- ./qml/GuiIE.qml
-
-
-
diff --git a/internal/frontend/share/fontawesome-webfont.ttf b/internal/frontend/share/fontawesome-webfont.ttf
deleted file mode 100644
index 35acda2f..00000000
Binary files a/internal/frontend/share/fontawesome-webfont.ttf and /dev/null differ
diff --git a/internal/frontend/share/info.rc b/internal/frontend/share/info.rc
deleted file mode 100644
index 3c3c9318..00000000
--- a/internal/frontend/share/info.rc
+++ /dev/null
@@ -1,45 +0,0 @@
-#define STRINGIZE_(x) #x
-#define STRINGIZE(x) STRINGIZE_(x)
-
-IDI_ICON1 ICON DISCARDABLE STRINGIZE(ICO_FILE)
-
-#if defined BUILD_BRIDGE
- #define FILE_COMMENTS "The Bridge is an application that runs on your computer in the background and seamlessly encrypts and decrypts your mail as it enters and leaves your computer."
- #define FILE_DESCRIPTION "ProtonMail Bridge"
- #define INTERNAL_NAME STRINGIZE(EXE_NAME)
- #define PRODUCT_NAME "ProtonMail Bridge for Windows"
-#elif defined BUILD_IE
- #define FILE_COMMENTS "The Import-Export app helps you to migrate your emails from local files or remote IMAP servers to ProtonMail or simply export emails to local folder."
- #define FILE_DESCRIPTION "ProtonMail Import-Export app"
- #define INTERNAL_NAME STRINGIZE(EXE_NAME)
- #define PRODUCT_NAME "ProtonMail Import-Export app for Windows"
-#else
- #error No target specified
-#endif
-
-#define LEGAL_COPYRIGHT "(C) " STRINGIZE(YEAR) " Proton Technologies AG"
-
-1 VERSIONINFO
-FILEVERSION FILE_VERSION_COMMA,0
-PRODUCTVERSION FILE_VERSION_COMMA,0
-BEGIN
- BLOCK "StringFileInfo"
- BEGIN
- BLOCK "040904b0"
- BEGIN
- VALUE "Comments", FILE_COMMENTS
- VALUE "CompanyName", "Proton Technologies AG"
- VALUE "FileDescription", FILE_DESCRIPTION
- VALUE "FileVersion", STRINGIZE(FILE_VERSION)
- VALUE "InternalName", INTERNAL_NAME
- VALUE "LegalCopyright", LEGAL_COPYRIGHT
- VALUE "OriginalFilename", STRINGIZE(ORIGINAL_FILE_NAME)
- VALUE "ProductName", PRODUCT_NAME
- VALUE "ProductVersion", STRINGIZE(PRODUCT_VERSION)
- END
- END
- BLOCK "VarFileInfo"
- BEGIN
- VALUE "Translation", 0x0409, 0x04B0
- END
-END
\ No newline at end of file
diff --git a/internal/frontend/types/types.go b/internal/frontend/types/types.go
index a3edcdb7..6b546f53 100644
--- a/internal/frontend/types/types.go
+++ b/internal/frontend/types/types.go
@@ -20,8 +20,6 @@ package types
import (
"github.com/ProtonMail/proton-bridge/internal/bridge"
- "github.com/ProtonMail/proton-bridge/internal/importexport"
- "github.com/ProtonMail/proton-bridge/internal/transfer"
"github.com/ProtonMail/proton-bridge/internal/updater"
"github.com/ProtonMail/proton-bridge/pkg/pmapi"
)
@@ -108,43 +106,3 @@ func (b *bridgeWrap) GetUsers() (users []User) {
func (b *bridgeWrap) GetUser(query string) (User, error) {
return b.Bridge.GetUser(query)
}
-
-// ImportExporter is an interface of import-export needed by frontend.
-type ImportExporter interface {
- UserManager
-
- GetLocalImporter(string, string, string) (*transfer.Transfer, error)
- GetRemoteImporter(string, string, string, string, string, string) (*transfer.Transfer, error)
- GetEMLExporter(string, string, string) (*transfer.Transfer, error)
- GetMBOXExporter(string, string, string) (*transfer.Transfer, error)
- ReportBug(osType, osVersion, description, accountName, address, emailClient string) error
- ReportFile(osType, osVersion, accountName, address string, logdata []byte) error
-}
-
-type importExportWrap struct {
- *importexport.ImportExport
-}
-
-// NewImportExportWrap wraps import-export struct into local importExportWrap
-// to implement local interface.
-// The problem is that Import-Export returns the importexport package's User
-// type. Every method which returns User therefore has to be overridden to
-// fulfill the interface.
-func NewImportExportWrap(ie *importexport.ImportExport) *importExportWrap { //nolint[golint]
- return &importExportWrap{ImportExport: ie}
-}
-
-func (b *importExportWrap) FinishLogin(client pmapi.Client, auth *pmapi.Auth, mailboxPassword []byte) (User, error) {
- return b.ImportExport.FinishLogin(client, auth, mailboxPassword)
-}
-
-func (b *importExportWrap) GetUsers() (users []User) {
- for _, user := range b.ImportExport.GetUsers() {
- users = append(users, user)
- }
- return
-}
-
-func (b *importExportWrap) GetUser(query string) (User, error) {
- return b.ImportExport.GetUser(query)
-}